我一直在阅读MSDN上有关Unity(依赖注入,控制反转)的文章,但我认为我需要用简单的术语(或简单的示例)进行解释。我对MVPC模式很熟悉(我们在这里使用了它),但是我还不能真正掌握Unity的知识,我认为这是我们应用程序设计的下一步。
我一直在阅读MSDN上有关Unity(依赖注入,控制反转)的文章,但我认为我需要用简单的术语(或简单的示例)进行解释。我对MVPC模式很熟悉(我们在这里使用了它),但是我还不能真正掌握Unity的知识,我认为这是我们应用程序设计的下一步。
Answers:
Unity只是一个IoC“容器”。Google StructureMap,然后尝试一下。我想,当IoC东西对您来说是新手时,我会更容易理解。
基本上,如果您了解IoC,那么您就会知道您正在做的事情是在创建对象时反转控件。
没有IoC:
public class MyClass
{
   IMyService _myService; 
   public MyClass()
   {
      _myService = new SomeConcreteService();    
   }
}
使用IoC容器:
public class MyClass
{
   IMyService _myService; 
   public MyClass(IMyService myService)
   {
      _myService = myService;    
   }
}
如果没有IoC,则依赖IMyService的类必须更新要使用的服务的具体版本。但这有很多原因,这很糟糕(您已将类与IMyService的特定具体版本耦合,无法轻松对其进行单元测试,无法轻松进行更改,等等)。
使用IoC容器,您可以“配置”容器来为您解决这些依赖性。因此,使用基于构造函数的注入方案,只需将IMyService依赖项的接口传递给构造函数。使用容器创建MyClass时,容器将为您解决IMyService依赖项。
使用StructureMap,配置容器如下所示:
StructureMapConfiguration.ForRequestedType<MyClass>().TheDefaultIsConcreteType<MyClass>();
StructureMapConfiguration.ForRequestedType<IMyService>().TheDefaultIsConcreteType<SomeConcreteService>();
因此,您完成的工作将告诉容器:“当有人请求IMyService时,请给他们一份SomeConcreteService的副本。” 并且您还指定了,当有人要求MyClass时,他们会得到一个具体的MyClass。
这就是IoC容器的全部工作。他们可以做更多的事情,但这就是重点-他们为您解决依赖关系,因此您不必这样做(也不必在整个代码中使用“ new”关键字)。
最后一步:创建MyClass时,您将执行以下操作:
var myClass = ObjectFactory.GetInstance<MyClass>();
希望有帮助。随时给我发电子邮件。
我刚刚看了大卫·海顿(David Hayden)进行的30分钟的Unity Dependency Injection IoC Screencast,觉得这是一个很好的例子说明。这是显示笔记的摘录:
该截屏视频显示了Unity IoC的几种常见用法,例如:
Unity是一个像许多其他库一样的库,它使您无需自己创建就可以获取所请求类型的实例。所以给。
public interface ICalculator
{
    void Add(int a, int b);
}
public class Calculator : ICalculator
{
    public void Add(int a, int b)
    {
        return a + b;
    }
}
您将使用类似Unity的库来注册当请求ICalculator类型又称为IoC(控制反转)时返回的计算器(此示例是理论上的,在技术上不正确)。
IoCLlibrary.Register<ICalculator>.Return<Calculator>();
因此,现在当您想要ICalculator的实例时,您只需...
Calculator calc = IoCLibrary.Resolve<ICalculator>();
通常,每次解析类型时,通常都可以将IoC库配置为容纳单例或创建新实例。
现在,假设您有一个依赖于ICalculator的类,该类可以存在。
public class BankingSystem
{
    public BankingSystem(ICalculator calc)
    {
        _calc = calc;
    }
    private ICalculator _calc;
}
而且,您可以设置该库以在创建对象时将其注入到构造函数中。
因此,DI或依赖注入意味着注入其他对象可能需要的任何对象。
WilcoxTutorials这个家伙很好地演示了针对初学者的Unity容器。
第1部分:http://www.youtube.com/watch?v = CWwe9Z0Gyew
第2部分:http://www.youtube.com/watch?v = PsIbevgzQQE
在不到半小时的时间内,您将了解基本知识!
MSDN具有使用Unity进行依赖项注入的开发人员指南,这可能会很有用。
《开发人员指南》从什么是依赖项注入的基础开始,到如何使用Unity进行依赖项注入的示例继续。自2014年2月起,开发人员指南涵盖了Unity 3.0,该版本于2013年4月发布。
我将介绍ASP.NET Web API 2中的依赖注入的大多数示例
public interface IShape
{
    string Name { get; set; }
}
public class NoShape : IShape
{
    public string Name { get; set; } = "I have No Shape";
}
public class Circle : IShape
{
    public string Name { get; set; } = "Circle";
}
public class Rectangle : IShape
{
    public Rectangle(string name)
    {
        this.Name = name;
    }
    public string Name { get; set; } = "Rectangle";
}
在DIAutoV2Controller.cs中使用自动注入机制
[RoutePrefix("api/v2/DIAutoExample")]
public class DIAutoV2Controller : ApiController
{
    private string ConstructorInjected;
    private string MethodInjected1;
    private string MethodInjected2;
    private string MethodInjected3;
    [Dependency]
    public IShape NoShape { get; set; }
    [Dependency("Circle")]
    public IShape ShapeCircle { get; set; }
    [Dependency("Rectangle")]
    public IShape ShapeRectangle { get; set; }
    [Dependency("PiValueExample1")]
    public double PiValue { get; set; }
    [InjectionConstructor]
    public DIAutoV2Controller([Dependency("Circle")]IShape shape1, [Dependency("Rectangle")]IShape shape2, IShape shape3)
    {
        this.ConstructorInjected = shape1.Name + " & " + shape2.Name + " & " + shape3.Name;
    }
    [NonAction]
    [InjectionMethod]
    public void Initialize()
    {
        this.MethodInjected1 = "Default Initialize done";
    }
    [NonAction]
    [InjectionMethod]
    public void Initialize2([Dependency("Circle")]IShape shape1)
    {
        this.MethodInjected2 = shape1.Name;
    }
    [NonAction]
    [InjectionMethod]
    public void Initialize3(IShape shape1)
    {
        this.MethodInjected3 = shape1.Name;
    }
    [HttpGet]
    [Route("constructorinjection")]
    public string constructorinjection()
    {
        return "Constructor Injected: " + this.ConstructorInjected;
    }
    [HttpGet]
    [Route("GetNoShape")]
    public string GetNoShape()
    {
        return "Property Injected: " + this.NoShape.Name;
    }
    [HttpGet]
    [Route("GetShapeCircle")]
    public string GetShapeCircle()
    {
        return "Property Injected: " + this.ShapeCircle.Name;
    }
    [HttpGet]
    [Route("GetShapeRectangle")]
    public string GetShapeRectangle()
    {
        return "Property Injected: " + this.ShapeRectangle.Name;
    }
    [HttpGet]
    [Route("GetPiValue")]
    public string GetPiValue()
    {
        return "Property Injected: " + this.PiValue;
    }
    [HttpGet]
    [Route("MethodInjected1")]
    public string InjectionMethod1()
    {
        return "Method Injected: " + this.MethodInjected1;
    }
    [HttpGet]
    [Route("MethodInjected2")]
    public string InjectionMethod2()
    {
        return "Method Injected: " + this.MethodInjected2;
    }
    [HttpGet]
    [Route("MethodInjected3")]
    public string InjectionMethod3()
    {
        return "Method Injected: " + this.MethodInjected3;
    }
}
在DIV2Controller.cs中,所有内容将从Dependency Configuration Resolver类注入
[RoutePrefix("api/v2/DIExample")]
public class DIV2Controller : ApiController
{
    private string ConstructorInjected;
    private string MethodInjected1;
    private string MethodInjected2;
    public string MyPropertyName { get; set; }
    public double PiValue1 { get; set; }
    public double PiValue2 { get; set; }
    public IShape Shape { get; set; }
    // MethodInjected
    [NonAction]
    public void Initialize()
    {
        this.MethodInjected1 = "Default Initialize done";
    }
    // MethodInjected
    [NonAction]
    public void Initialize2(string myproperty1, IShape shape1, string myproperty2, IShape shape2)
    {
        this.MethodInjected2 = myproperty1 + " & " + shape1.Name + " & " + myproperty2 + " & " + shape2.Name;
    }
    public DIV2Controller(string myproperty1, IShape shape1, string myproperty2, IShape shape2)
    {
        this.ConstructorInjected = myproperty1 + " & " + shape1.Name + " & " + myproperty2 + " & " + shape2.Name;
    }
    [HttpGet]
    [Route("constructorinjection")]
    public string constructorinjection()
    {
        return "Constructor Injected: " + this.ConstructorInjected;
    }
    [HttpGet]
    [Route("PropertyInjected")]
    public string InjectionProperty()
    {
        return "Property Injected: " + this.MyPropertyName;
    }
    [HttpGet]
    [Route("GetPiValue1")]
    public string GetPiValue1()
    {
        return "Property Injected: " + this.PiValue1;
    }
    [HttpGet]
    [Route("GetPiValue2")]
    public string GetPiValue2()
    {
        return "Property Injected: " + this.PiValue2;
    }
    [HttpGet]
    [Route("GetShape")]
    public string GetShape()
    {
        return "Property Injected: " + this.Shape.Name;
    }
    [HttpGet]
    [Route("MethodInjected1")]
    public string InjectionMethod1()
    {
        return "Method Injected: " + this.MethodInjected1;
    }
    [HttpGet]
    [Route("MethodInjected2")]
    public string InjectionMethod2()
    {
        return "Method Injected: " + this.MethodInjected2;
    }
}
配置依赖关系解析器
public static void Register(HttpConfiguration config)
{
    var container = new UnityContainer();
    RegisterInterfaces(container);
    config.DependencyResolver = new UnityResolver(container);
    // Other Web API configuration not shown.
}
private static void RegisterInterfaces(UnityContainer container)
{
    var dbContext = new SchoolDbContext();
    // Registration with constructor injection
    container.RegisterType<IStudentRepository, StudentRepository>(new InjectionConstructor(dbContext));
    container.RegisterType<ICourseRepository, CourseRepository>(new InjectionConstructor(dbContext));
    // Set constant/default value of Pi = 3.141 
    container.RegisterInstance<double>("PiValueExample1", 3.141);
    container.RegisterInstance<double>("PiValueExample2", 3.14);
    // without a name
    container.RegisterInstance<IShape>(new NoShape());
    // with circle name
    container.RegisterType<IShape, Circle>("Circle", new InjectionProperty("Name", "I am Circle"));
    // with rectangle name
    container.RegisterType<IShape, Rectangle>("Rectangle", new InjectionConstructor("I am Rectangle"));
    // Complex type like Constructor, Property and method injection
    container.RegisterType<DIV2Controller, DIV2Controller>(
        new InjectionConstructor("Constructor Value1", container.Resolve<IShape>("Circle"), "Constructor Value2", container.Resolve<IShape>()),
        new InjectionMethod("Initialize"),
        new InjectionMethod("Initialize2", "Value1", container.Resolve<IShape>("Circle"), "Value2", container.Resolve<IShape>()),
        new InjectionProperty("MyPropertyName", "Property Value"),
        new InjectionProperty("PiValue1", container.Resolve<double>("PiValueExample1")),
        new InjectionProperty("Shape", container.Resolve<IShape>("Rectangle")),
        new InjectionProperty("PiValue2", container.Resolve<double>("PiValueExample2")));
}