找到正确的成分根的.NET库 [英] Locate the correct composition root for a .NET library

查看:248
本文介绍了找到正确的成分根的.NET库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的说法,最主要的是

依赖注入(DI)友好库

IOC / DI - 为什么我要引用的所有图层/入门组件应用?

和这个文章(和其他各种材料)。

and this article (and other various material).

不过这并不清楚,我在哪里放置成分根库(DLL).NET项目。该项目不属于在文章中提到任何特定的类型。在台式机,控制台或这一点上,而不是明确的规定,甚至Web应用程序

However it's not clear to me where to place composition root in library (DLL) .NET project. The project does not belong to any specific type mentioned in the article. In desktop, console or even web application this point is instead clearly defined.

我目前的做法是包装容器,注册类型和重新露出解决方法:

My current approach is to wrap the container, register types and re-expose the Resolve method:

class DefaultBootstrapper : IBootstrapper {
  public Bootstrapper() {
    _container = new XXXContainer();
    RegisterTypes(_container);
  }

  public T Resolve<T>() where T : class {
    return _container.Resolve<T>();
  }

  // + other _container.Resolve() overloads

  private readonly XXXContainer _container;
}



然后,我阻止库消费者打造的根实例的库(如定义的内部构造),因此强制使用一个单工厂的:

Then I prevent library consumers to create root instances of the library (e.g. defining internal constructors) and hence forcing the use of a singleton factory:

class XYZFactory {
  static XYZFactory() {}

  private XYZFactory(IBootstrapper bootstrapper) {
    _bootstrapper = bootstrapper;
  }

  public static XYZFactory Instance {
    get { return Singleton; }
  }

  public ABCType CreateABCType(string param1) {
    return _bootstrapper.Resolve<ABCType>(param1, _bootstrapper.Resolve<Dependency1>); 
  }

  private static readonly XYZFactory Singleton = XYZFactory(new DefaultBootstrapper);
  private readonly IBootstrapper _bootstrapper;
}



现在的问题是,有一个更好的方法或更好的模式来使用的定位在库项目在成分根

推荐答案

这取决于库要创建的类型。是你自己的解决方案库项目的一部分,或者是其他开发人员的团队,部门,甚至可能是组织外部依赖于可重用库?

It depends on the type of library you are creating. Is your library project part of your own solution, or is it a reusable library that other developers depend upon outside your team, department, or perhaps even organization?

在的情况下它仅仅是一个解决方案的库项目部分,库项目应本身通常不包含组成根源。根据定义,成分根是在一个(最好)独特的地理位置其中,模块组合在一起的应用程序。换句话说,你的解决方案将有一个或多个启动项目(如MVC应用程序,WCF服务,控制台应用程序),并且每次启动的项目将获得自己的根组成。图层的下方不会得到自己组成的根。

In the case of it being just a library project part of a solution, the library project should itself typically not contain a composition root. By definition, the composition root is a "(preferably) unique location in an application where modules are composed together". In other words, your solution would have one or multiple start-up projects (such as a MVC application, WCF service, console app), and each start-up project would get its own composition root. Layers below would not get their own composition root.

这BTW并不意味着你不应该阻止组成根部内代码重复。当有很多引起了包括项目(如DAL和BLL)默认布线的重复,你通常应提取此逻辑到另一个项目。您可以通过包括内部的项目之一(最有可能的BLL)注册逻辑的一部分,这样做,让这一共同逻辑各组成根调用,或者您可以通过添加一个特殊的引导程序项目该项目做到这一点,引用的项目。这个引导程序项目只容器注册逻辑。通过从应用程序组件分离这个逻辑您阻止需要在使用依赖注入框架依赖这些组件。这不过通常不是一个问题,如果一个组装地依赖于这样的框架下,只要你确保应用程序的逻辑一直采取在容器上的依赖免费的。

This btw does not mean that you should not prevent code duplication inside the composition roots. When there is a lot of duplication caused by a default wiring for included projects (such as DAL and BLL), you should typically extract this logic to another project. You can either do this by including part of the registration logic inside one of the projects (most likely the BLL) and let each composition root call that shared logic, or you can do this by adding a special 'bootstrapper' project for that project and the referenced projects. This bootstrapper project will only container the registration logic. By separating this logic from the application assemblies you prevent those assemblies from needing a dependency on the used dependency injection framework. It is however usually not a problem if a assembly takes a dependency on such framework, as long as you make sure the application logic keeps free from taking dependencies on the container.

可重复使用的框架的东西通常是不同的。在这种情况下,消费者会用你的库,但你必须对他们如何构建自己的应用程序的控制。常常希望的,因为它可以直接被消费者所消耗的方式来提供该库,而不必做各种复杂的登记在其组成根。你常常甚至不知道他们是否有一个组成根都没有。

For reusable frameworks things are usually different. In that case consumers will use your library, but you have no control over how they structure their application. You often want to supply the library in a way that it can directly be consumed by consumers, without having to do all kinds of 'complex' registration in their composition root. You often don't even know if they have a composition root at all.

在这种情况下你通常应该让你的库,而无需DI容器的工作。你应该自己不要采取这样的容器上的依赖,因为这将拖累在容器中。如果你使用的容器,问自己,为什么你的可重复使用的库使用的容器,如果这必须。也许你做,因为你设计围绕依赖注入的原则,所有类型;因为这使测试更容易。不要忘记,这是你的问题,你的消费者不是问题。作为一个框架设计者,你应该很难在得到您的框架可用,尽可能不给消费者。

In that case you should typically make your library working without a DI container. You should yourself not take a dependency on such a container, because this would drag the container in. If you do use a container, question yourself why your reusable library uses a container, and if this has to be. Perhaps you do because you designed all types around the dependency injection principle; because this makes testing easier. Don't forget that this is your problem, not the problem of your consumers. As a framework designer, you should hard in getting your framework as usable as possible for your consumers.

<击>有几个招数,可以帮助你在这里。例如,定义调用到内部构造函数,所有依赖公共默认构造函数。这是一个被称为穷人芒注入的模式,通常是一个反模式。这是一个LOB应用程序使用时,反模式。但正如我所解释的,可重用的库是不同的,因为你不控制代码的用户,但你必须确保向后版本之间的兼容性。具有内部构造函数的依赖让您的单元测试来调用构造函数(通过使用的 InternalsVisibleToAttribute )。

<击>另一个技巧是使用工厂。定义一个工厂接口和内部工厂实现。该实现可以调用这些类型的内部构造。

<击>如果您的可重复使用的项目有依赖于DI框架,尝试提取接线逻辑和提供一个额外的引导程序汇编。这使得消费者用自己的DI框架,而不必引用DI框架您选择适合您的库。

如果你正在建设一个可重用库,看看马克塞曼这个博客后

In case you are building a reusable library, take a look at this blog post from Mark Seemann.

这篇关于找到正确的成分根的.NET库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆