Unity实例的access属性

本文关键字:属性 access 实例 Unity | 更新日期: 2023-09-27 18:05:30

我在构造器上实现了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(); 
    }
}

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

我不能改变A的实现!!List<>应该在构造函数中接收。

Unity实例的access属性

C类的构造函数做的太多了;注入器构造函数应该很简单。因此,在构建对象图时不调用GetList,而是推迟到稍后的时刻,在AC中都注入IB,如下所示:

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;
    }
}

这简化了您的注册,您的代码,并允许您自信地编写对象图。

如果类型不受您的控制,您应该考虑使用第三方类型。一般来说,您应该小心让容器自动连接这样的类型,因为维护该类型的人可能会向该类型添加新的构造函数,这可能会破坏您的DI注册(更多信息在这里)。

因此,与其让容器自动连接该类型,不如注册一个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,并且代理只会在DoSomething第一次执行时创建A,这将是在创建完整的对象图之后。

或者,您的代理也可以只依赖于IB并在内部创建lazy。就像这样:

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只在代理构建完成后调用。

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

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()); 
    }

但是正如我所说,它对现有代码的影响更大