2010-07-15 76 views
3

这对大多数人来说似乎很明显,但我只是想确认依赖注入(DI)依赖于接口的使用。依赖注入(DI)依赖于接口吗?

更具体地说,对于在其构造函数中具有某个接口作为参数的类或者定义为属性(又名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)

针对这种情况的任何建议?

回答

6

它不需要使用接口 - 你可以使用具体类型或抽象基类。但是,在使用接口时,DI的许多优点(如能够改变依赖性的实现)都会出现。

Castle Windsor(我最熟悉的DI框架)允许您将IoC容器中的对象映射到Interfaces或名称,这可以在您的案例中起作用。

+0

我给你的绿色复选标记,但大卫和彼得的答案也很好。感谢您澄清接口不是必需的。 – Pretzel 2010-07-15 17:42:53

8

DI真的只是意味着一个类不会构造它的外部依赖关系,并且不会管理这些依赖关系的生命周期。依赖关系可以通过构造函数或通过方法参数注入。接口或抽象类型通常用于阐明消费者对其依赖关系的期望合约,但在某些情况下也可以注入简单类型。

例如,库中的一个类可能会在内部调用HttpContext.Current,这使得代码将被托管在应用程序中的任意假设。库方法的DI版本会希望通过参数注入HttpContext实例等

3

依赖注入是一种组织代码的方式。也许你的一些混淆来自于没有一种官方的方式来实现它。它可以通过使用“常规”c#代码或使用Castle Windsor之类的框架来实现。有时(通常?)这涉及使用接口。无论如何实现,DI的总体目标通常是让代码更容易测试,并且稍后可以更容易地进行修改。

如果您要通过构造函数在您的示例中注入URL,那么可以将其视为“手动”DI。 DI上的维基百科article有更多手动与框架DI的例子。

+0

是的,我同意。有些混乱来自于那里,没有一个标准化的做法。 DI已经通过“Pro ASP.net MVC Framework”书籍(由Sanderson提供)呈现给我,并且每个示例都使用接口,所以我的结论是它只能在Interfaces上工作,但从逻辑上讲,它在我的脑海中没有意义,所以我不得不问。桑德森在他的第一本书中谈到了温莎城堡,但现在在他的第二版中使用了Ninject(上周刚刚从印刷机上脱颖而出。)是的,我开始意识到DI对单元测试有很大帮助。 – Pretzel 2010-07-15 17:47:27

1

我想重点关注在.NET应用程序中使用接口。 .NET中的多态性可以通过虚拟或抽象方法或接口来实现。

在所有情况下,都有一个方法签名,根本没有实现或者可以被覆盖的实现。

定义了函数(甚至是属性)的'契约',但是如何实现该方法,该方法的逻辑内容可以在运行时不同,由哪个子类实例化并传入方法或构造函数,或设置属性('注入'行为)。

官方的.NET类型设计指导方针鼓吹在接口上使用抽象基类,因为它们在发布后有更好的选择来发展它们,可以包括方便的重载,并且能够更好地自我记录并向实现者传递正确的用法。

但是,必须注意不要添加任何逻辑。这样做的诱惑已经烧毁了过去许多人使用的接口 - 许多其他人使用接口,只是因为程序员围坐在他们身上。

有趣的是,虽然DI本身很少被过度使用,但是使用框架来执行注入通常被过度使用以增加复杂性的损害,链式反应可能发生在更多容器中需要更多类型,即使它们从未“切换”。

应该谨慎使用IoC框架,通常只有当您需要根据环境或配置在运行时交换对象时才需要使用IoC框架。这通常意味着切换应用程序中的主要组件“接缝”,例如用于抽象数据层的存储库对象。

对于我来说,IoC框架的真正威力在于在无法控制创建的地方切换实现。例如,在ASP.NET MVC中,控制器类的创建由ASP.NET框架执行,因此注入任何东西都是不可能的。 ASP.NET框架有一些钩子,IoC框架可以用来在创建过程中“介入”并执行其魔术。

卢克