【问题标题】:Object creation using Unity Application Block使用 Unity 应用程序块创建对象
【发布时间】:2014-12-15 23:36:07
【问题描述】:

我目前正在阅读 Microsoft Unity 应用程序块,以便在我的个人项目之一中使用它。我已经阅读了几篇关于它的文章和教程,但我有一个问题。

this example about the framework 中,他们使用Unity 来创建一个继承IVehicle 接口的对象。继承自它的 3 个类没有任何必须在构造函数中初始化的属性,因此一切正常。

显然,在我的项目中,情况并非总是如此。我将有一些需要在构造函数中初始化属性(或字段)的类。我的问题是,我将如何实现这一目标?或者是 Unity 自己无法做到的事情;我必须使用 Unity 的 Resolve() 函数创建对象,该函数会给我一个具有未初始化字段/属性的对象,然后我必须在每个字段/属性上一一调用设置器?

【问题讨论】:

    标签: c# wpf dependency-injection inversion-of-control unity-container


    【解决方案1】:

    Unity 支持自动连接,它允许您解析复杂的对象图,而不仅仅是单个对象。

    例如,假设您有一个类Car 实现ICar,它依赖于另一个类IEngine,使用构造函数注入(汽车的构造函数需要一个IEngine 类型的参数)。

    public interface ICar
    {
        void Accelerate();
    }
    
    public interface IEngine
    {
        void Accelerate();
    }
    
    public class Car: ICar
    {
        private readonly IEngine _engine;
        public Car(IEngine engine)      
        {
            _engine = engine;
        }
    
        public void Accelerate()
        {
            _engine.Accelerate();
        }
    }
    
    public class Engine: IEngine
    {       
        public Engine()     
        {       
        }
    
        public string Message {get; set;}
    
        public void Accelerate()
        {
            Console.WriteLine("Accelerating." + Message);
        }
    }
    

    然后您将在 Unity 中注册如何解析 ICarIEngine

    var _container = new UnityContainer()   
                        .RegisterType<ICar,Car>()
                        .RegisterType<IEngine,Engine>(
                              new InjectionProperty("Message", "Hello world"));
    

    然后,当您解析ICar 时,Unity 将能够向Car 构造函数提供Engine 的实例,自动连接 Car 对 IEngine 的依赖项。对于 CarEngine 可能具有的任何其他依赖项以及为注入注册的任何属性也是如此。

    var car = _container.Resolve<Car>();
    car.Accelerate();
    

    加速。你好世界

    这种方式通过解析ICar Unity 将为您提供所需的完整对象图。你可以试试样品in this fiddle

    编辑

    您可以使用将在运行时执行的 lambda 方法注册要解析的类型,例如:

    public interface IFoo
    {
        DateTime ResolvedTime {get; set;}
    }
    
    public class Foo: IFoo
    {
        public DateTime ResolvedTime {get; set;}
    }
    
    //Can be registered using a lambda as in:
    container.RegisterType<IFoo,Foo>(
                 new InjectionFactory(c => new Foo{ ResolvedTime = DateTime.Now }));
    

    你可以得到一些信息on the msdn。我还用这个 lambda 示例更新了上面的小提琴。

    【讨论】:

    • 您的回答帮助我更好地理解。但是,如果说Engine 需要一个我只能在稍后解决时提供的Message,而我在申请开始时的注册时不知道Message,会发生什么? Unity 对我来说似乎非常有限,因为您必须在注册对象时在应用程序的一开始就将所有参数提供给构造函数、所有属性等。除非我还遗漏了什么?
    • 您还可以使用将在运行时执行的 lambda 注册类型。如果这还不够,那么您可以创建一个像 ICarFactory 这样的抽象工厂接口,因此某些类可能依赖于这个工厂,并且会调用类似 carFactory.CreateCar() 的东西,而不是直接依赖于 ICar
    • 您能否举一个例子,使用 Unity 和 lambda 表达式在上面的答案中注册类型?或者指向我的文档?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多