找到 .NET 库的正确组合根目录

本文关键字:组合 根目录 NET 找到 | 更新日期: 2023-09-27 17:57:15

我在这里阅读了有关该论点的其他各种问题,最值得注意的是

依赖关系注入 (DI) "友好"库

Ioc/DI - 为什么我必须在输入应用程序中引用所有层/组件?

和这篇文章(以及其他各种材料)。

但是,我不清楚在库 (DLL) .NET 项目中放置组合根的哪个位置。该项目不属于本文中提到的任何特定类型。在桌面、控制台甚至 Web 应用程序中,这一点是明确定义的。

我目前的方法是包装容器,注册类型并重新公开 Resolve 方法:

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;
}

然后,我阻止库使用者创建库的根实例(例如定义内部构造函数),从而强制使用单例工厂:

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;
}

问题是,有更好的方法或更好的模式来定位库项目中的合成根吗?

找到 .NET 库的正确组合根目录

这取决于您正在创建的库的类型。您的库项目是您自己的解决方案的一部分,还是其他开发人员在您的团队、部门甚至组织之外依赖的可重用库?

如果它只是解决方案的库项目部分,则库项目本身通常不应包含组合根。根据定义,组合根是"模块组合在一起的应用程序中(最好)唯一位置"。换句话说,您的解决方案将具有一个或多个启动项目(如 MVC 应用程序、WCF 服务、控制台应用),并且每个启动项目都将获得自己的组合根。下面的图层不会获得自己的合成根。

顺便说一句,这并不意味着您不应该阻止组合根中的代码重复。当包含的项目(如 DAL 和 BLL)的默认连接导致大量重复时,通常应将此逻辑提取到另一个项目。您可以通过在其中一个项目(很可能是 BLL)中包含部分注册逻辑并让每个组合根调用该共享逻辑来执行此操作,也可以通过为该项目和引用的项目添加一个特殊的"引导程序"项目来执行此操作。此引导程序项目将仅包含注册逻辑。通过将此逻辑与应用程序程序集分离,可以防止这些程序集需要依赖于使用的依赖项注入库。但是,如果程序集依赖于此类库,则通常不是问题,只要确保应用程序逻辑不依赖于容器即可。

对于可重用的库,情况通常是不同的。在这种情况下,使用者将使用您的库,但您无法控制他们如何构建其应用程序。您通常希望以消费者可以直接使用的方式提供库,而不必在其组合根中进行各种"复杂"注册。你通常甚至不知道它们是否有组合根。

在这种情况下,通常应使库在没有 DI 容器的情况下工作。您自己不应该依赖这样的容器,因为这会拖入容器。如果您确实使用容器,请问问自己为什么可重用库使用容器,以及是否必须这样做。也许你这样做是因为你围绕依赖注入原则设计了所有类型;因为这使测试更容易。不要忘记,这是你的问题,而不是你的消费者的问题。作为一个可重用的库设计者,你应该努力让你的库尽可能对你的消费者可用。请不要假设您的使用者正在使用 DI 容器。即使他们练习依赖注入,他们也可能应用 Pure DI 而不是 DI 容器。

如果您正在构建可重用的库,请查看 Mark Seemann 的这篇博客文章。