我一直在阅读有关Unity(依赖注入,控制反转)的MSDN文章,但我认为我需要用简单的术语(或简单的例子)来解释它。我熟悉MVPC模式(我们在这里使用它),但我还不能真正掌握这个Unity的东西,我认为这是我们应用程序设计的下一步。
答案 0 :(得分:165)
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>();
希望有所帮助。随时给我发电子邮件。
答案 1 :(得分:36)
我刚看过David Hayden的30分钟Unity依赖注入IoC截屏,并认为这是一个很好的解释示例。以下是节目笔记的摘录:
截屏视频显示了Unity IoC的几种常见用法,例如:
答案 2 :(得分:31)
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或依赖注入意味着注入另一个可能需要的对象。
答案 3 :(得分:29)
这个人WilcoxTutorials提供了针对初学者的Unity容器的精彩演示。
第1部分:http://www.youtube.com/watch?v=CWwe9Z0Gyew
第2部分:http://www.youtube.com/watch?v=PsIbevgzQQE
在不到半小时的时间内,您将了解基础知识!
答案 4 :(得分:9)
Unity是IoC。 IoC的要点是抽象类型本身之外的类型之间的依赖关系。这有几个优点。首先,它集中完成,这意味着当依赖关系发生变化时,您不必更改大量代码(单元测试可能就是这种情况)。
此外,如果使用配置数据而不是代码完成连接,您实际上可以在部署后重新连接依赖关系,从而在不更改代码的情况下更改应用程序的行为。
答案 5 :(得分:5)
MSDN有Developer's Guide to Dependency Injection Using Unity可能有用。
开发人员指南首先介绍了依赖注入的基础知识,并继续介绍如何使用Unity进行依赖注入。截至2014年2月,开发人员指南涵盖了2013年4月发布的Unity 3.0。
答案 6 :(得分:2)
我将介绍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")));
}
答案 7 :(得分:0)