有人能解释一下微软的联合吗?

我一直在阅读 mSDN 上关于 Unity (依赖注入,控制反转)的文章,但我认为我需要用简单的术语(或简单的例子)来解释它。我熟悉 MVPC 模式(我们在这里使用它) ,但是我还不能真正理解 Unity 这个东西,我认为它是我们应用程序设计的下一步。

111904 次浏览

Unity 只是一个 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 时,给他们一个 Some ConcreteService 的副本。”您还指定,当有人请求 MyClass 时,他们将得到一个具体的 MyClass。

这就是物联网集装箱的作用。它们可以做更多的事情,但这正是它的主旨——它们为您解决依赖关系,因此您不必这样做(并且您不必在整个代码中使用“ new”关键字)。

最后一步: 当你创建你的 MyClass 时,你会这样做:

var myClass = ObjectFactory.GetInstance<MyClass>();

希望能帮上忙,随时给我发邮件。

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 被请求时返回(这个例子是理论上的,不是技术上的正确控制反转)。

IoCLlibrary.Register<ICalculator>.Return<Calculator>();

所以现在当你想要一个计算器的实例时,你只需要..。

Calculator calc = IoCLibrary.Resolve<ICalculator>();

通常可以将 IoC 库配置为在每次解析类型时保存一个单例或创建一个新实例。

现在让我们假设你有一个依赖于微计算器的类。

public class BankingSystem
{
public BankingSystem(ICalculator calc)
{
_calc = calc;
}


private ICalculator _calc;
}

您还可以设置库,以便在创建对象时将其注入到构造函数中。

所以 DI 或者依赖注入意味着注入另一个可能需要的对象。

联合是一个物联网。IoC 的要点是抽象类型本身之外的类型之间的依赖关系的连接。这有几个好处。首先,它是集中完成的,这意味着当依赖关系发生变化时,您不必更改大量代码(单元测试可能就是这种情况)。

此外,如果连接是使用配置数据而不是代码完成的,那么您实际上可以在部署后重新连接依赖项,从而在不更改代码的情况下更改应用程序的行为。

我刚刚看了30分钟由大卫海登制作的 Unity 依赖注入的 IoC 屏幕播放,觉得这是一个很好的例子解释。以下是节目说明的片段:

这段视频展示了 Unity IoC 的一些常见用法,比如:

  • 创建不在容器中的类型
  • 注册和解析类型映射
  • 注册和解析命名类型映射
  • 单例、 LifetimeManager 和 ContainerControlledLifetimeManager
  • 注册现有实例
  • 向现有实例中注入依赖项
  • 通过 App.config/Web.config 填充 UnityContainer
  • 通过注入 API 指定依赖项,而不是依赖项属性
  • 使用嵌套(父-子)容器

MSDN 有一个可能有用的 开发者使用 Unity 依赖注入指南

开发者指南从依赖注入的基本知识开始,然后是如何使用 Unity 依赖注入的例子。截至2014年2月,《开发者指南》涵盖了2013年4月发布的 Unity 3.0。

我将介绍 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")));
}