15

Ninject を使用して構築したい次のクラスがあるとします。矢印は依存関係を示しています。

A > B > D
A > C > D

A が一時的にスコープされるように Ninject を構成したい、つまり、Ninject に A を要求するたびに、新しい A を取得します。また、B と C を一時的なものにしたいと考えています。A を要求するたびに新しいものを取得します。しかし、B と C の両方でDを再利用したいと考えています。したがって、A を要求するたびに、Ninject が必要です。 2 つの D ではなく、各オブジェクトの 1 つを構築します。しかし、D を別の As で再利用したくありません。

Ninject を使用してこれを設定する最良の方法は何ですか?

更新:
さらに調査した結果、Unity には、私が探していることを行う PerResolveLifetimeManager があるようです。Ninjectに相当するものはありますか?

4

3 に答える 3

15

Ninjectは、すぐに使用できる4つの組み込みオブジェクトスコープ(Transient、Singleton、Thread、Request)をサポートします。

したがって、同様のスコープはありません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);

サンプルクラスは次のとおりです。

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 { }
于 2012-12-26T18:36:47.357 に答える
1

1 つの代替方法は、依存関係を自分で構築することです。

var kernel = new StandardKernel();
kernel.Bind<A>().ToMethod(ctx =>
{
    var d = new D();
    var c = new C(d);
    var b = new B(d);
    var a = new A(b, c);
    return a;
});

これは好ましい方法ではないかもしれませんが、 、、およびAの新しいインスタンスを使用して の新しいインスタンスを常に構築します(ただし、 forおよびの同じインスタンスを再利用します)。への呼び出しを追加できますが、これはデフォルトのスコープであるため必須ではありません。BCDDBCInTransientScope()

于 2012-12-26T20:08:46.667 に答える