使用Unity访问实例的属性

时间:2014-05-28 15:22:47

标签: c# dependency-injection unity-container

我在构造函数上实现了Unity注入。我有以下内容:

interface IA
{
    DoSomething();
}

class A : IA
{
    private List<MyType> List;
    public A(List<MyType> list) 
    {
        this.List = list;
    }

    DoSomething()
    {
       // do something with this.List
    }
}
interface IB
{
    List<MyType> GetList();
}
class B : IB
{
    public List<MyType> GetList() { }
}

class C
{
    private A MyA;
    public C(IB b)
    {
        this.MyA = new A(b.GetList());
    }

    public DoSomethingInA()
    {
        this.MyA.DoSomething(); 
    }
}

我想删除&#34;新的A()&#34;在类C的构造函数中并使用IA的注入但我不知道如何在构造函数中注册接收类型IA的A实例的属性而不是实例本身。

我无法改变A的实施!列表&lt;&gt;应该在构造函数中收到。

提前致谢!

2 个答案:

答案 0 :(得分:1)

C的构造函数做得太多; injector constructors should be simple。因此,不要在构建对象图时调用GetList,而是将其推迟到稍后时刻,只需在IBA注入C,如下所示:

class A : IA
{
    private IB b;
    public A(IB b) {
        this.b = b;
    }

    DoSomething() {
        var list = this.b.GetList();
       // do something with this.List
    }
}

class C
{
    private IB b;
    public C(IB b) {
        this.b = b;
    }
}

这简化了您的注册和代码,并允许您compose object graphs with confidence

<强>更新

如果类型不受控制,您应该将其视为第三方类型。通常,您应该小心让容器自动连接这种类型,因为维护该类型的人可能会为该类型添加新的构造函数,这可能会破坏您的DI注册(更多信息here)。

因此,不要让容器自动连接该类型,而是注册一个创建该第三方类型实例的lambda表达式。例如:

container.Register<IA>(new InjectionFactory(c => new A(c.Resolve<IB>().GetList()))); 

请注意,在这种情况下,在构建对象图时,您仍然做得太多,并且(取决于GetList在封面下的内容)可能会更难以验证正确性图表。

因此,您正在使用在构造期间依赖于某些运行时类型的第三方类型,您可能需要考虑推迟该类型的创建。如果您为IA创建代理类,则可以延迟A的创建,而无需应用程序知道任何相关内容。该代理可能看起来像这样:

class DelayedAProxy : IA
{
    private readonly Lazy<IA> a;
    public DelayedAProxy(Lazy<IA> a) {
        this.a = a;
    }

    public DoSomething() {
        this.a.Value.DoSomething();
    }
}

您可以按如下方式注册:

container.Register<IA>(new InjectionFactory(c =>
{
    var lazy = new Lazy<IA>(() => new A(c.Resolve<IB>().GetList()));
    new DelayedAProxy(lazy);
}));

此处我们不直接注册A,而是注册DelayedAProxy,而该代理只会在第一次执行A时创建DoSomething,这将在创建完整的对象图之后。

或者,您的代理也可以依赖IB并在内部创建惰性。这就是:

class DelayedAProxy : IA
{
    private readonly Lazy<IA> a;
    public DelayedAProxy(IB b) {
        this.a = new Lazy<IA>(() => new A(b.GetList()));
    }

    public DoSomething() {
        this.a.Value.DoSomething();
    }
}

这样做的好处是DelayedAProxy的注册变得更加容易:

container.RegisterType<IA, DelayedAProxy>();

虽然看起来在这种情况下DelayedAProxy构造函数再次做了很多,实际上它只是用委托创建了Lazy。只有在构建代理后才会调用GetList

答案 1 :(得分:0)

我最终改变了设计并使用方法而不是构造函数注入依赖项,如:

interface IA
{
    Initialize(List<something> list);
    DoSomething();
}

class C
{
    private IA MyA;
    public C(IB b, IA a)
    {
        this.MyA = a;
        this.MyA.Initialize(b.GetList()); 
    }

    public DoSomethingInA()
    {
        this.MyA.DoSomething(); 
    }
}

初始化在构造函数中完成,以减少当前代码调用DoSomething()的影响,也可能是:

    public DoSomethingInA()
    {
        this.MyA.DoSomething(b.GetList()); 
    }

但正如我所说,它对现有代码的影响要大得多。