C# 有人可以解释一下 Microsoft Unity 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/608585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can someone explain Microsoft Unity?
提问by Ryan Abbott
I've been reading the articles on MSDN about Unity (Dependency Injection, Inversion of Control), but I think I need it explained in simple terms (or simple examples). I'm familiar with the MVPC pattern (we use it here), but I just can't really grasp this Unity thing yet, and I think it's the next step in our application design.
我一直在阅读 MSDN 上关于 Unity(依赖注入、控制反转)的文章,但我认为我需要用简单的术语(或简单的例子)来解释它。我熟悉 MVPC 模式(我们在这里使用它),但我还不能真正掌握 Unity 这个东西,我认为这是我们应用程序设计的下一步。
采纳答案by Chris Holmes
Unity is just an IoC "container". Google StructureMap and try it out instead. A bit easier to grok, I think, when the IoC stuff is new to you.
Unity 只是一个 IoC“容器”。谷歌 StructureMap 并尝试一下。我认为,当 IoC 的东西对你来说是新的时,更容易理解。
Basically, if you understand IoC then you understand that what you're doing is inverting the control for when an object gets created.
基本上,如果您了解 IoC,那么您就会明白您所做的是在创建对象时反转控制。
Without IoC:
没有 IoC:
public class MyClass
{
IMyService _myService;
public MyClass()
{
_myService = new SomeConcreteService();
}
}
With IoC container:
使用 IoC 容器:
public class MyClass
{
IMyService _myService;
public MyClass(IMyService myService)
{
_myService = myService;
}
}
Without IoC, your class that relies on the IMyService has to new-up a concrete version of the service to use. And that is bad for a number of reasons (you've coupled your class to a specific concrete version of the IMyService, you can't unit test it easily, you can't change it easily, etc.)
如果没有 IoC,依赖 IMyService 的类必须更新要使用的服务的具体版本。由于多种原因,这很糟糕(您已将您的类与 IMyService 的特定具体版本耦合,您无法轻松对其进行单元测试,您无法轻松更改它,等等)
With an IoC container you "configure" the container to resolve those dependencies for you. So with a constructor-based injection scheme, you just pass the interface to the IMyService dependency into the constructor. When you create the MyClass with your container, your container will resolve the IMyService dependency for you.
使用 IoC 容器,您可以“配置”容器来为您解决这些依赖项。因此,使用基于构造函数的注入方案,您只需将 IMyService 依赖项的接口传递给构造函数。当您使用容器创建 MyClass 时,您的容器将为您解析 IMyService 依赖项。
Using StructureMap, configuring the container looks like this:
使用 StructureMap,配置容器如下所示:
StructureMapConfiguration.ForRequestedType<MyClass>().TheDefaultIsConcreteType<MyClass>();
StructureMapConfiguration.ForRequestedType<IMyService>().TheDefaultIsConcreteType<SomeConcreteService>();
So what you've done is told the container, "When someone requests the IMyService, give them a copy of the SomeConcreteService." And you've also specified that when someone asks for a MyClass, they get a concrete MyClass.
所以你所做的就是告诉容器,“当有人请求 IMyService 时,给他们一份 SomeConcreteService 的副本。” 您还指定了当有人要求 MyClass 时,他们会得到一个具体的 MyClass。
That's all an IoC container really does. They can do more, but that's the thrust of it - they resolve dependencies for you, so you don't have to (and you don't have to use the "new" keyword throughout your code).
这就是 IoC 容器的全部功能。它们可以做更多的事情,但这就是它的主旨——它们为您解决依赖关系,因此您不必这样做(并且您不必在整个代码中使用“new”关键字)。
Final step: when you create your MyClass, you would do this:
最后一步:当您创建 MyClass 时,您将执行以下操作:
var myClass = ObjectFactory.GetInstance<MyClass>();
Hope that helps. Feel free to e-mail me.
希望有帮助。随时给我发电子邮件。
回答by Chad Moran
Unity is a library like many others that allows you to get an instance of a requested type without having to create it yourself. So given.
Unity 是一个与许多其他库一样的库,它允许您获取所请求类型的实例,而无需自己创建它。所以给予。
public interface ICalculator
{
void Add(int a, int b);
}
public class Calculator : ICalculator
{
public void Add(int a, int b)
{
return a + b;
}
}
You would use a library like Unity to register Calculator to be returned when the type ICalculator is requested aka IoC (Inversion of Control) (this example is theoretical, not technically correct).
当请求类型 ICalculator 又名 IoC(控制反转)时,您将使用像 Unity 这样的库来注册要返回的计算器(此示例是理论上的,技术上不正确)。
IoCLlibrary.Register<ICalculator>.Return<Calculator>();
So now when you want an instance of an ICalculator you just...
所以现在当你想要一个 ICalculator 的实例时,你只需......
Calculator calc = IoCLibrary.Resolve<ICalculator>();
IoC libraries can usually be configured to either hold a singleton or create a new instance every time you resolve a type.
IoC 库通常可以配置为在每次解析类型时保存一个单例或创建一个新实例。
Now let's say you have a class that relies on an ICalculator to be present you could have..
现在假设您有一个依赖于 ICalculator 的类,您可以拥有..
public class BankingSystem
{
public BankingSystem(ICalculator calc)
{
_calc = calc;
}
private ICalculator _calc;
}
And you can setup the library to inject a object into the constructor when it's created.
并且您可以设置库以在创建对象时将对象注入到构造函数中。
So DI or Dependency Injection means to inject any object another might require.
所以 DI 或依赖注入意味着注入另一个可能需要的任何对象。
回答by Brian Rasmussen
Unity is an IoC. The point of IoC is to abstract the wiring of dependencies between types outside of the types themselves. This has a couple of advantages. First of all, it is done centrally which means you don't have to change a lot of code when dependencies change (which may be the case for unit tests).
Unity 是一个 IoC。IoC 的重点是抽象类型本身之外的类型之间的依赖关系。这有几个优点。首先,它是集中完成的,这意味着您不必在依赖项更改时更改大量代码(单元测试可能就是这种情况)。
Furthermore, if the wiring is done using configuration data instead of code, you can actually rewire the dependencies after deployment and thus change the behavior of the application without changing the code.
此外,如果连接是使用配置数据而不是代码完成的,您实际上可以在部署后重新连接依赖项,从而在不更改代码的情况下更改应用程序的行为。
回答by Kevin Hakanson
I just watched the 30 minute Unity Dependency Injection IoC Screencast by David Hayden and felt that was a good explaination with examples. Here is a snippet from the show notes:
我刚刚观看了 David Hayden 的 30 分钟 Unity 依赖注入 IoC 截屏视频,我觉得这是一个很好的例子解释。以下是节目笔记的片段:
The screencast shows several common usages of the Unity IoC, such as:
截屏视频显示了 Unity IoC 的几种常见用法,例如:
- Creating Types Not In Container
- Registering and Resolving TypeMappings
- Registering and Resolving Named TypeMappings
- Singletons, LifetimeManagers, and the ContainerControlledLifetimeManager
- Registering Existing Instances
- Injecting Dependencies into Existing Instances
- Populating the UnityContainer via App.config / Web.config
- Specifying Dependencies via Injection API as opposed to Dependency Attributes
- Using Nested ( Parent-Child ) Containers
- 创建不在容器中的类型
- 注册和解析类型映射
- 注册和解析命名类型映射
- Singletons、LifetimeManagers 和 ContainerControlledLifetimeManager
- 注册现有实例
- 将依赖注入现有实例
- 通过 App.config / Web.config 填充 UnityContainer
- 通过注入 API 指定依赖项而不是依赖项属性
- 使用嵌套(父子)容器
回答by Ben Power
This guy WilcoxTutorials gives an excellent demonstration of the Unity container that is aimed at beginners.
这家伙 WilcoxTutorials 对面向初学者的 Unity 容器进行了出色的演示。
Part 1: http://www.youtube.com/watch?v=CWwe9Z0Gyew
第 1 部分:http: //www.youtube.com/watch?v=CWwe9Z0Gyew
Part 2: http://www.youtube.com/watch?v=PsIbevgzQQE
第 2 部分:http: //www.youtube.com/watch?v=PsIbevgzQQE
In less than half an hour and you will understand the basics!
在不到半小时的时间内,您将了解基础知识!
回答by Simon Tewsi
MSDN has a Developer's Guide to Dependency Injection Using Unitythat may be useful.
MSDN 有一个Developer's Guide to Dependency Injection Using Unity可能很有用。
The Developer's Guide starts with the basics of what dependency injection is, and continues with examples of how to use Unity for dependency injection. As of the February 2014 the Developer's Guide covers Unity 3.0, which was released in April 2013.
开发人员指南从什么是依赖注入的基础知识开始,然后是如何使用 Unity 进行依赖注入的示例。截至 2014 年 2 月,开发人员指南涵盖了 2013 年 4 月发布的 Unity 3.0。
回答by Narottam Goyal
I am covering most of the examples of Dependency Injection in ASP.NET Web API 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";
}
In DIAutoV2Controller.cs Auto Injection mechanism is used
在 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;
}
}
In DIV2Controller.cs everything will be injected from the Dependency Configuration Resolver class
在 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;
}
}
Configuring the Dependency Resolver
配置依赖解析器
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")));
}