C# 写一个依赖注入的库;已启用";

C# 写一个依赖注入的库;已启用";,c#,dependency-injection,class-library,C#,Dependency Injection,Class Library,我现在正在做一个项目,主要是基于图书馆的 我希望使用依赖项注入来使用库,但我希望库在很大程度上与所使用的容器无关 不久前我写了一个“桥”库来简化这类事情,但我不确定这是否真的是正确的方法?(图书馆:) 我不想直接从我的库中引用DI技术(Ninject、Windsor等),因为这样会使使用它的人变得不灵活 在这方面还有一些类似的问题,但似乎没有一个能令人满意地解决这个问题 作为旁注:我意识到我可以确保库遵循一般习惯用法,使用接口和参数作为依赖项,然后让消费应用程序在容器中注册类型 我能看到的唯一问

我现在正在做一个项目,主要是基于图书馆的

我希望使用依赖项注入来使用库,但我希望库在很大程度上与所使用的容器无关

不久前我写了一个“桥”库来简化这类事情,但我不确定这是否真的是正确的方法?(图书馆:)

我不想直接从我的库中引用DI技术(Ninject、Windsor等),因为这样会使使用它的人变得不灵活

在这方面还有一些类似的问题,但似乎没有一个能令人满意地解决这个问题

作为旁注:我意识到我可以确保库遵循一般习惯用法,使用接口和参数作为依赖项,然后让消费应用程序在容器中注册类型


我能看到的唯一问题(如果我错了,请纠正我)是,这要求消费应用程序实际知道哪些类型链接到哪些接口,是否需要将某些类型注册为Singleton等。。。从即插即用的使用角度来看,这相当糟糕。

我认为您对依赖注入的范围有点误解。DI是一种模式,是IoC的一个子集,IoC容器使DI变得简单方便——它们有助于解决依赖关系。IoC可以归类为多种方法的超集

您不需要IoC框架来实现依赖注入。

如果你真的坚持使用IoC容器而不是利用常规DI(即构造函数参数或强制属性设置),那么你应该指定容器/框架,不要试图通过将适配器或桥接器混在一起来满足所有人的需要。对过度设计要谨慎。从其定义来看,库意味着它有一组有限且定义良好的功能,因此它不需要注入大量依赖项

他们很可能希望实现一些接口的自己版本

你不需要一个国际奥委会框架来实现这一点。如果您的构造函数将其参数定义为接口,那么实际上您已经实现了DI——依赖项在构造时被注入,而您对它的实际具体实现一无所知。让调用代码担心它想要传递接口的哪个实现的细节。

这有点难,但我建议使用穷人的注入。我并不是说它很棒,但它在一些约束条件下有一些有效的用例(就像服务定位器)。这将需要更多的维护,但它将节省您依赖另一个图书馆为国际奥委会容器注册。你应该读这方面的书

我最近在我的一个非常小的团队中实现了这种方法。基本上,您为库的公共类编写了两个构造函数

internal SitemapProvider(IActionResultFactory actionResultFactory, IBaseUrlProvider baseUrlProvider)
{
    _actionResultFactory = actionResultFactory;
    _baseUrlProvider = baseUrlProvider;
}

public SitemapProvider() : this(new ActionResultFactory(), new BaseUrlProvider()) { }
正如您所看到的,只有第二个构造函数是公共的,您自己填充依赖项。这还提供了程序集级别的封装。您仍然可以通过向程序集添加属性并在库中自由使用依赖项注入来测试此类。用户还可以使用new关键字创建实例,或将此类的接口添加到其IoC注册中

我不知道在.NET中是否有广泛采用的IoC容器注册库。我曾想过自己写一个,但每个容器都有其独特的特性,而且对象生命周期会使它变得更加复杂。人们也会不安地依赖另一个库来实现这一点。

一个好的DI实现应该在任何对象上启用DI,不管后者是否是DI不可知的

Prism是一个坏例子,因为我上次使用它时(2年前),它强制使用
[Injection]
属性,要求对象是不可知的。一个不依赖DI的好例子是(非常流行的Java DI框架,有一个名为.NET的端口),它允许通过所谓的上下文文件启用DI——这些是描述依赖关系的xml文件。后者不必是库的一部分,而是作为一个完全独立的dll文件

Spring的示例可以告诉您,除了编程到接口范例之外,您不应该为了使对象可注入或允许对象被注入而遵循任何特定的配置、先决条件或模式,并允许对合适的构造函数和属性设置器进行编程访问


这并不意味着任何DI框架都应该支持对普通CLR(.NET)对象的操作,即POCO-s。有些框架只依赖于它们的特定机制,可能不适合与DI无关的代码一起使用。通常,它们需要直接依赖于DI框架来访问库,我认为您希望(而且可能应该)避免这种情况

你需要允许用户注入他们自己的实现(插件)吗?@UfukHacıoğulları不一定不需要。他们很可能想要实现他们自己版本的一些接口,然后他们可以随意丢弃它们来代替任何其他引用。然而,库本身可能不会直接围绕着这种实现。-1因为这显然不是所有库的情况,其中一些库虽然范围很窄,但规模相当大。我还提到,我意识到可以简单地大致遵循模式,然后用户可以选择自行连接,但这并不太好。为库使用单一的IoC容器类型也不太好,因为这样一些用户就无法将其集成到自己的应用程序中