对大多数人来说这似乎是显而易见的,但我只是想确认依赖注入(DI)依赖于Interfaces的使用。
更具体地说,对于在其构造函数中具有某个接口作为参数的类或者定义为属性(也称为Setter)的某个接口的情况,DI框架可以将具体类的实例移交给满足该类中该接口的需求。 (如果这个描述不清楚,请道歉。我无法正确描述这一点,因为术语/概念对我来说仍然有点新鲜。)
我问的原因是我目前有一个具有各种依赖关系的类。不是对象依赖,而是URL。这个类看起来像这个[C#]:
using System.Web.Services.Protocols;
public partial class SomeLibraryService : SoapHttpClientProtocol
{
public SomeLibraryService()
{
this.Url = "http://MyDomainName.com:8080/library-service/jse";
}
}
SoapHttpClientProtocol类有一个名为Url
的公共属性(它是一个普通的旧“字符串”),这里的构造函数将其初始化为硬编码值。
我可以使用DI框架在构造中注入不同的值吗?我在想,因为this.Url
不是Interface
;这是一个String
。
[顺便提一下,根据我正在使用的代码中的注释,上面的代码是“由wsdl自动生成的”。所以我并不特别想改变这段代码,尽管我也没有看到自己重新生成它。所以可能更改此代码很好。]
我可以看到自己制作了一个替代构造函数,它将一个字符串作为参数并以这种方式初始化this.Url
,但我不确定这是关于保持松散耦合的关注点分离的正确方法。 (SoC)的
对这种情况有什么建议吗?
答案 0 :(得分:8)
DI真的只是意味着一个类不会构造它的外部依赖关系,并且不会管理这些依赖关系的生命周期。可以通过构造函数或方法参数注入依赖项。接口或抽象类型通常用于阐明消费者期望与其依赖关系的契约,但在某些情况下也可以注入简单类型。
例如,库中的类可能会在内部调用HttpContext.Current,这会对代码将托管的应用程序进行任意假设。库方法的DI版本希望通过参数注入HttpContext实例,等
答案 1 :(得分:5)
不需要使用接口 - 您可以使用具体类型或抽象基类。但是在使用接口时,DI的许多优点(例如能够改变依赖的实现)都会出现。
Castle Windsor(我最了解的DI框架),允许您将IoC容器中的对象映射到接口,或者只是名称,这可以适用于您的情况。
答案 2 :(得分:3)
依赖注入是一种组织代码的方法。也许你的一些困惑来自于没有一种官方方式可以做到这一点。它可以使用“常规”c#代码,或使用像Castle Windsor这样的框架来实现。有时(经常?)这涉及使用接口。无论如何实现,DI的主要目标通常是让您的代码更容易测试,以后更容易修改。
如果您要通过构造函数在示例中注入URL,那么可以将其视为“手动”DI。关于DI的维基百科article有更多的手册与框架DI的例子。
答案 3 :(得分:1)
我想回答的重点是在.NET应用程序中使用接口。 .NET中的多态性可以通过虚拟或抽象方法或接口来实现。
在所有情况下,都有一个根本没有实现的方法签名或者可以覆盖的实现。
定义函数(甚至是属性)的“契约”但是如何实现该方法,该方法的逻辑内容在运行时可以是不同的,由哪个子类实例化并传入该方法确定或构造函数,或在属性上设置('注入'的行为)。
官方的.NET类型设计指南主张在接口上使用抽象基类,因为它们在发布后有更好的选择来演变它们,可以包括方便的重载,并且能够更好地自我记录并向实现者传达正确的用法。
但是,必须注意不要添加任何逻辑。过去这样做的诱惑已经烧毁了很多人使用界面 - 许多其他人使用界面只是因为那是程序员围坐在他们周围的界面。
同样有趣的是,虽然DI本身很少被过度使用,但使用框架进行注射通常会过度使用而不利于增加复杂性,链式反应可能会发生在越来越多的地方容器中需要类型,即使它们从未被“切换”。
IoC框架应该谨慎使用,通常只有在需要根据环境或配置在运行时交换对象时才使用。这通常意味着在应用程序中切换主要组件“接缝”,例如用于抽象数据层的存储库对象。
对我而言,IoC框架的真正强大之处在于将实现切换到您无法控制创建的位置。例如,在ASP.NET MVC中,控件类的创建由ASP.NET框架执行,因此注入任何内容都是不可能的。 ASP.NET框架有一些钩子,IoC框架可以用它来“介入”创建过程并执行它们的魔力。
路