代码之家  ›  专栏  ›  技术社区  ›  Ryan Abbott

有人能解释一下微软的团结吗?

  •  141
  • Ryan Abbott  · 技术社区  · 15 年前

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

    7 回复  |  直到 6 年前
        1
  •  162
  •   Mihai Alexandru-Ionut    6 年前

    团结只是国际奥委会的“容器”。谷歌结构地图,并尝试它代替。我想,当国际奥委会的东西对你来说是新的时候,摸索会容易一些。

    基本上,如果您了解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>();
    

    希望有帮助。请随时给我发电子邮件。

        2
  •  35
  •   Andy    9 年前

    我刚刚看了大卫海登30分钟的Unity Dependency Injection IOC屏幕,觉得这是一个很好的例子解释。以下是演示说明中的一个片段:

    屏幕显示了Unity IOC的几种常见用法,例如:

    • 创建不在容器中的类型
    • 注册和解析类型映射
    • 注册和解析命名类型映射
    • singleton、lifetimemanagers和containerControlledlifetimemanager
    • 正在注册现有实例
    • 将依赖项注入现有实例
    • 通过app.config/web.config填充UnityContainer
    • 通过注入API指定依赖项,而不是依赖项属性
    • 使用嵌套(父-子)容器
        3
  •  30
  •   Chad Moran    15 年前

    Unity是一个库,与其他许多库一样,它允许您获取请求类型的实例,而不必自己创建。这么说。

    public interface ICalculator
    {
        void Add(int a, int b);
    }
    
    public class Calculator : ICalculator
    {
        public void Add(int a, int b)
        {
            return a + b;
        }
    }
    

    当类型icalcutator被请求时,您将使用一个类似于Unity的库来注册要返回的计算器aka ioc(控制反转)(这个例子是理论上的,技术上不正确)。

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

    所以现在当你想要一个计算器的实例时,你只是…

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

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

    现在让我们假设你有一个类,它依赖于一个计算器来呈现你可以拥有的。

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

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

    所以DI或依赖注入意味着注入其他对象可能需要的任何对象。

        4
  •  28
  •   RayLoveless    11 年前

    这个家伙Wilcoxtutorials为面向初学者的Unity容器提供了一个极好的演示。

    第1部分: http://www.youtube.com/watch?v=CWwe9Z0Gyew

    第2部分: http://www.youtube.com/watch?v=PsIbevgzQQE

    不到半个小时,你就会明白基本原理!

        5
  •  9
  •   Brian Rasmussen    15 年前

    团结是国际奥委会。IOC的要点是抽象类型本身之外的类型之间的依赖关系连接。这有几个优点。首先,它是集中完成的,这意味着当依赖关系发生变化时,不必更改很多代码(单元测试可能就是这样)。

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

        6
  •  5
  •   Simon Elms    10 年前

    MSDN有 Developer's Guide to Dependency Injection Using Unity 这可能有用。

    开发人员指南从什么是依赖注入的基础开始,并以如何使用Unity进行依赖注入的示例继续。截至2014年2月,《开发商指南》涵盖了2013年4月发布的Unity 3.0。

        7
  •  2
  •   piet.t Charis A.    6 年前

    我将介绍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中,所有内容都将从依赖配置解析程序类注入

    [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")));
    }