统一与自定义依赖注入?

Unity vs custom dependency injection?

我正在尝试证明使用 Unity 进行依赖项注入与自定义界面的合理性,例如:

public interface IResolver
{
   ITypeA TypeA { get; }
   ITypeB TypeB { get; }
}

public static ResolverFactory
{
   // set by unit tests or Main() method, etc.
   public static IResolver DefaultResolver { get; set; }
}

为什么要选择像 Unity 框架这样更复杂的方法?

如果您希望实现自己的 DI 实现,我建议您首先研究 Unity、Autofac、StructureMap 或 Ninject。

为什么?简单地说:不要重新发明轮子。 DI 库已经编写完成并且非常灵活。他们也有针对 ASP.NET MVC 的各种挂钩。当您可以利用现有库时,编写自己的库会做更多的工作。如果您真的需要自己的实现,那就去做吧,但我认为那里有许多 DI 库之一可以满足您的需求。

DI 本质上是复杂的。在简单的场景中应用 DI,就像在教程和示例中经常做的那样,乍一看似乎总是矫枉过正。当应用程序复杂时,DI才开始支付股息。

当你有一个复杂的应用程序时,添加 DI 来组合应用程序是有意义的。使用基于约定的配置(大多数 DI 容器开箱即用地支持)可以节省数百或数千行配置代码,并使应用程序更易于维护。您的简单 DI 容器没有基于约定的配置。

编写自己的 DI 容器并不是重新发明轮子。轮子很简单,DI 很复杂。编写自己的 DI 容器更像是重新发明灯泡。当您可以获得一个功能齐全的(事实上是免费的)并将其拧紧到位时,为什么还要麻烦呢?

另外,你完全没有抓住重点。您发明的是 service locator. A DI container is not normally used in that way. Most DI containers have a built-in ability to automatically recursively inject dependencies into the constructors of entire object graphs. They are typically used for application composition,而不是服务位置。这是他们的主要目的。

为了使您的简单 DI 容器以这种方式工作,您将需要使用反射加载每种类型,分析构造函数并提出一些标准化的方法来选择最佳方法,然后加载所有依赖类型(构造函数参数)及其依赖关系等递归。然后你必须从对象图的底部开始,使用反射递归调用每种类型的最佳构造函数来创建每种类型的实例。在创建实例本身之前递归创建每个实例的依赖关系,直到组成整个对象图。您可能最终还需要重新发明一种方法来进行 属性 注入。只需下载 NuGet 包并阅读现有 DI 容器的文档,即可避免所有这些工作。

我强烈推荐你阅读这本书Dependency Injection in .NET。 DI 是软件开发中最容易被误解的概念之一,值得投资自己详细研究该主题,而不必筛选 Internet 上的错误信息。正确使用 DI 可以获得很多好处,但使用不当通常比根本不使用 DI 更糟糕。更不用说,这本书为您提供了 负载 世界不需要另一个 DI 容器实现的其他原因。

哦,最后一件事 - 不要使用 Unity。 Unity 是最差的 DI 容器之一,它缺少几个重要的特性。另一方面,Autofac、Ninject、StructureMap、Castle Windsor 都是不错的选择。