Ninject作用域 - 在构建的整个图形中使用相同的实例

Rat*_*eek 15 ninject inversion-of-control

假设我有以下要使用Ninject构造的类,其中箭头显示依赖关系.

A > B > D
A > C > D
Run Code Online (Sandbox Code Playgroud)

我想配置Ninject使得A是瞬态范围的,即每次你向Ninject询问A时,你都会得到一个新的.我也希望B和C是瞬态的,每次你要求A时你都会得到一个新的.但我希望D可以在B和C中重复使用.所以每次我要求A,我想要Ninject构造每个对象之一,而不是两个Ds.但我不希望Ds在不同的As中重复使用.

使用Ninject进行设置的最佳方法是什么?

更新:
经过一些研究后,似乎Unity有一个PerResolveLifetimeManager来完成我正在寻找的东西.是否有Ninject等价物?

nem*_*esv 15

Ninject支持开箱即用的四个内置对象范围:瞬态,单例,线程,请求.

因此,没有任何PerResolveLifetimeManager类似的范围,但您可以通过使用该InScope方法注册自定义范围轻松实现它.

事实证明,有一个现有的Ninject扩展:ninject.extensions.namedscope它提供了InCallScope您正在寻找的方法.

但是,如果您想自己动手,可以使用自定义InScope委托.在哪里可以使用IRequest类型的主对象A将其用作范围对象:

var kernel = new StandardKernel();
kernel.Bind<A>().ToSelf().InTransientScope();
kernel.Bind<B>().ToSelf().InTransientScope();
kernel.Bind<C>().ToSelf().InTransientScope();
kernel.Bind<D>().ToSelf().InScope(
    c =>
        {
            //use the Request for A as the scope object                         
            var requestForA = c.Request;
            while (requestForA != null && requestForA.Service != typeof (A))
            {
                requestForA = requestForA.ParentRequest;
            }
            return requestForA;
        });

var a1 = kernel.Get<A>();    
Assert.AreSame(a1.b.d, a1.c.d);

var a2 = kernel.Get<A>();    
Assert.AreSame(a2.b.d, a2.c.d);

Assert.AreNotSame(a1.c.d, a2.c.d);
Run Code Online (Sandbox Code Playgroud)

样本类是:

public class A
{
    public readonly B b;
    public readonly C c;
    public A(B b, C c) { this.b = b; this.c = c; }
}

public class B
{
    public readonly D d;
    public B(D d) { this.d = d; }
}

public class C
{
    public readonly D d;  
    public C(D d) { this.d = d; }
}

public class D { }
Run Code Online (Sandbox Code Playgroud)


Rat*_*eek 6

我找到了我的具体问题的解决方案,即由ninject.extensions.namedscope扩展提供的 InCallScope.这与Unity PerResolveLifetimeManager概念的行为相同.