我已经使用这个概念很长一段时间了.通常我会使用DI(而不是服务定位器)方法在我的代码中实现IoC.
以下是我对IoC的理解.
如果classA依赖于classB,如果它在其中声明了classB的实例.它依赖于classB,由于某种原因(我稍后会谈到),不好,因此我们使用DI来解决这个问题.所以现在我们有一个名为IClassB的接口,它将在classA的构造函数中传递(我在这里采用构造函数注入,为了说明).这里是代码:
public class ClassA { IClassB _classBObj = null; public ClassA(IClassB classBObj) { _classBObj = classBObj; } public void UseClassBMethod() { this._classBObj.classBMethod(); } } public class ClassB:IClassB { public void classBMethod() { //Some task carried out by classB. } } public interface IClassB { void classBMethod(); }
这里有代码使它运行:
class Program { static void Main(string[] args) { //This code is outside of class A and hence declaring //object of ClassB is not dependency ClassA classA=new ClassA(new ClassB); classA.UseClassBMethod(); } }
我已经演示了上面的例子,以确保我对IoC和DI的理解是否正确.如果您发现任何错误,请纠正我.
现在,当我试图找出IoC的原因时,我发现了两个重要原因:
>可测试性:当然是正确的问题.让我们假设,在上面的例子中,例如,classB方法使用SMPTP服务器或某些WCF / Webservice,我们可能无法测试它.但是,我们可以创建一个实现接口IClassB的测试存根类,并通过传递测试存根类的实例继续进行测试.
>在具体实施方面的依赖性:这是我无法与之相处的.即使我使用以下代码更改classA的代码:
public class ClassA { ClassB _classBObj = null; public ClassA() { _classBObj = new ClassB(); } public void UseClassBMethod() { this._classBObj.classBMethod(); } }
IoC如何帮助摆脱由于ClassB对象的classB方法的变化而引起的任何问题?如果方法签名有任何变化,我们也必须在接口IClassB的方法签名中进行更改(事实上,这正在增加重构任务.).如果方法实现更改说例如它需要额外的日志记录任务,则更改将仅限于ClassB代码.
我可能对这个问题看起来有点愚蠢,但是有人会提出这样一种场景(除了单元可测性之外)我们从这种方法中受益了吗?
非常感谢您阅读本文.
这里的核心概念是您针对接口进行编程.您的代码不知道任何具体的类.
因此,您可以在不影响代码的情况下切换具体实现.
在您的情况下,您可以替换ClassA classA = new ClassA(new ClassB);使用ClassA classA = new ClassA(new ClassC);其中有
不同的行为,是更少或更优或需要一些密码来做某事等.
我们的想法是,如果ClassC遵循ClassB也实现的接口,那么您可以更改为不使用ClassC
您的代码中的任何更改
如果界面发生变化,您的代码当然会受到影响.这是你无法避免的.
但是你获得的是,你可以在不影响代码的情况下切换和更改具体实现,并且这种更改比根据您的需要正确定义的接口更频繁地需要和发生.