这是最受关注的概念之一:Ioc(控制反转)。
我已经使用了很长时间了。通常,我会使用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代码。

我可能对这个问题有些愚蠢,但是有人可以提出一个方案(除了单元可测试性之外),使我们从这种方法中受益吗?

非常感谢您阅读本文。

最佳答案

这里的核心概念是您program against an interface
您的代码不知道任何具体的类。

因此,您可以在不影响代码的情况下切换具体的实现。

在您的情况下,您可以将ClassA classA=new ClassA(new ClassB);替换为ClassA classA=new ClassA(new ClassC);
不同的行为或多或少是最佳选择,或者需要某些密码才能执行其他操作。

这个想法是,如果ClassC遵循ClassB也会实现的接口,那么您可以更改为使用ClassC而无需
您代码中的任何更改

如果界面更改,那么您的代码当然会受到影响。这是你无法避免的。

但是您得到的是,您可以在不影响代码的情况下切换和更改具体的实现,并且这种更改比根据您的需求正确定义的接口更需要发生和发生。

07-26 04:46
查看更多