为什么我必须使用IoC统一

时间:2014-05-22 20:31:00

标签: c# unit-testing design-patterns inversion-of-control unity-container

我创建了一个适用于依赖性反转原理的类,并使用依赖注入模式,如下所示:

public interface ITypeOfPrinter
{
    string Printing();
}

public class Print
{  
    private readonly ITypeOfPrinter _typeOfPrinter;

    public Print(ITypeOfPrinter typeOfPrinter)
    {
        _typeOfPrinter = typeOfPrinter;
    }

    public string print()
    {
        return _typeOfPrinter.Printing();
    }
}

public class BlackAndWhitePrinter : ITypeOfPrinter
{
    public string Printing()
    {
        NumberOfPrints++;
        return string.Format("it is Black and white printing {0}", NumberOfPrints);
    }

    public int NumberOfPrints { get; set; }

}
public class ColorfullPrinter : ITypeOfPrinter
{
    public string Printing()
    {
        NumberOfPrints++;
        return string.Format("it is colorfull printing {0}", NumberOfPrints);
    }
    public int NumberOfPrints { get; set; }
}

因此,如果我想使用BlackAndWhitePrinter,我只需创建一个实例对象并将其提供给我的Print类,其构造如下:

ITypeOfPrinter typeofprinter = new BlackAndWhitePrinter();
Print hp = new Print(typeofprinter);
hp.print();

那么为什么我必须在这里使用Unity或其他IoC框架?我已经做了我想要的事情:

var unityContainer = new UnityContainer();
unityContainer.RegisterType<ITypeOfPrinter, BlackAndWhitePrinter>();
var print = unityContainer.Resolve<Print>();
string colorfullText = print.print();

2 个答案:

答案 0 :(得分:7)

作为模式的依赖注入有助于使您的应用程序代码更易于维护。 DI框架(也称为IoC容器)可以帮助Composition Root更易于维护。

但是,如果IoC容器不能帮助您使组合根更易于维护,请不要在该方案中使用它!但这并不意味着您不应该使用依赖注入或其他有助于使您的软件更易于维护的模式和原则。您应该尽一切可能降低正在构建的软件的total cost of ownership

答案 1 :(得分:5)

正如史蒂文的答案的附录一样,使用IOC框架有几个令人信服的理由,这些框架不适用于您提供的简单示例,但可以轻松申请更复杂的应用程序;但是我同意,如果你觉得它没有带来好处,你实际上不必使用它。

当您的类不是由您直接创建时,而是由框架创建。

典型的例子是ASP.NET Controller / ApiController。你永远不会自己实例化这些,ASP.NET框架会为你做这件事。在这种情况下,如果你的控制器有依赖关系,那么IOC框架允许你通过控制器上的接口轻松声明这些依赖关系,而不用担心它们是如何被提供的。

这会使您的类分离,并允许更容易的单元测试,因为您可以模拟/存根依赖项。

当您有必须构建的复杂对象图时。以下是我正在处理的项目的匿名但其他真实图表:

 new DeathStar(new NotAMoon(),
               new PlanetExploder(),
                new ExhaustPort(new CriticalVulnerabilityIgnorer()),
                new StormTrooperGenerator(new DodgyBlasterGenerator(),
                    new HeadDoorBumper(new Ouch()),
                    new ShieldGenerator(new FurryCreatureVulnerability)),
                    new DramaticDuel(new Saber()), new DeadJedi()),
                new DroidFactory(),
                new TrashCompactor(new Monster()),
                new Emperor(new Vader())
            );

不知道你,但是当我需要一个新的IDeathStar时,我不会想要输入它(更不用说尝试维护或调试它了) - 我更愿意说< / p>

var moon= IOCFrameworkOfChoice.Resolve<IDeathStar>();

或更现实地说:

public class MyController: Controller
{
    public MyController(IDeathStar star)
    {
        //at runtime, at this point I have an armed and fully operational IDeathStar
        //without having to worry about where it came from!
    }
}