4

依存性注入アプローチ(Ninjectを使用)を使用してライブラリを開発しようとしていますが、設計が正しくないために、ある種の混乱が生じている可能性があります。要約すると、私のデザインアプローチは

  1. parentオブジェクトにはオブジェクトがありますcommon
  2. parentオブジェクトは、いくつかの可変数のオブジェクトを使用しますchild
  3. すべてのchildオブジェクトは、オブジェクトとまったく同じcommonオブジェクトインスタンスを使用する必要がありparentます

これが私の問題領域の単純なモデルです。

interface IParent : IDisposable {
    void Operation();
}
interface ICommon : IDisposable {
    void DoCommonThing();
}
interface IChild1 {
    void DoSomething();
}
interface IChild2 {
    void DoAnotherThing();
}
class Parent : IParent {
    private readonly ICommon _common;
    public Parent(ICommon common) {
        _common = common;
    }
    public void Dispose() {
        _common.Dispose();
    }
    public void Operation() {
        var c1 = ObjectFactory.GetInstance<IChild1>();
        c1.DoSomething();
        var c2 = ObjectFactory.GetInstance<IChild2>();
        c2.DoAnotherThing();
        // number of childs vary, do things until cn
        _common.DoCommonThing();
    }
}
class Common : ICommon {
    private bool _isDisposed;
    public void Dispose() {
        _isDisposed = true;
    }
    public void DoCommonThing() {
        if (_isDisposed) 
            throw new Exception("Common Object is Disposed");
    }
}
class Child1 : IChild1
{
    private readonly ICommon _common;
    public Child1(ICommon common) {
        _common = common;
    }
    public void DoSomething() {
        // Do Something...
        _common.DoCommonThing();
    }
}
class Child2 : IChild2 {
    private readonly ICommon _common;
    public Child2(ICommon common) {
        _common = common;
    }
    public void DoAnotherThing() {
        // Do Another Thing...
        _common.DoCommonThing();
    }
}

問題1

必要なchildオブジェクトの数は異なります。たとえば、c1.DoSomethingIの戻り値に応じて、他の子オブジェクトが必要な場合と不要な場合があります。したがって、コンストラクターを介してそれらを注入するのではなく、必要なときに作成するだけです。しかし、このアプローチはハリウッドの原則に違反します。

質問1

コンストラクターを介して子オブジェクトを挿入せずに、この違反をどのように防ぐことができますか?

問題2

childオブジェクトがそのオブジェクトと同じcommonオブジェクトインスタンスを使用するようにしたいparent。したがって、オブジェクトの存続期間はcommonその親と同じである必要があります。

  1. ICommonに有効期間が定義されていない場合、すべてのchildオブジェクトには独自のcommonオブジェクトインスタンスがあります。

  2. ICommonの有効期間がスレッドまたはリクエストスコープで定義されている場合parent、同じスレッドまたはリクエストスコープでオブジェクトの異なるインスタンスを使用することはできません。各parentオブジェクトは独自の新しいcommonオブジェクトを使用して破棄する必要があるためです。

そのため、私が知っているライフタイムスコープオプションを使用してそれを解決することはできませんでした。この2番目の問題に対して別の解決策を作成しましたが、コードが悪化します。

まず、オブジェクトにICommon注入する代わりに、オブジェクト自体がそれを作成しますparentparentObjectFactory

class Parent : IParent {
    private readonly ICommon _common;
    public Parent() {
        _common = ObjectFactory.GetInstance<ICommon>();
    }
.....

次に、オブジェクトにICommon注入する代わりに、オブジェクトは子オブジェクトのオブジェクトを設定します。childparentcommon

interface IChild {
    ICommon Common { get; set; }
}
interface IChildN : IChild {
     void DoNthThing();
}
abstract class ChildBase : IChild {
    ICommon IChild.Common { get; set; }
}
class ChildN : IChildN {
     public void DoNthThing() { }
}
class Parent : IParent {
    private readonly ICommon _common;
    public void Operation() {
        var c1 = ObjectFactory.GetInstance<IChild1>();
        c1.Common = _common;
        c1.DoSomething();
        var c2 = ObjectFactory.GetInstance<IChild2>();
        c2.Common = _common;
        c2.DoAnotherThing();
        _common.DoCommonThing();
    }
}

childしかし、このソリューションは再びハリウッドの原則に違反しているため、各オブジェクトの共通プロパティを設定する必要があります。

質問2

依存性注入を使用して、オブジェクトはどのようにオブジェクトをparentオブジェクトに分散できますか?(できればNinjectを使用)commonchild

質問3

これは私の問題についてもう少し一般的です:依存性注入をこのモデルに正しく適用するにはどうすればよいですか?

注:NinjectのObjectFactory.GetInstance呼び出しKernel.Get

4

1 に答える 1

3

CallScopeまたはのいずれかを使用する必要がありますNamedScope。これらはNinject.Extensions.NamedScopeパッケージの一部です。これにより、共通オブジェクトのスコープを親に設定できるため、すべての子リクエストが同じ共通オブジェクトを受け取ります。

子オブジェクトの作成について。アルゴリズムに応じて子オブジェクトを要求する必要がある場合は、ファクトリでインスタンス化する必要があります。Ninject.Extensions.Factoryこれを実現するには、パッケージを使用してください。これにより、コンテキストが保持され、親コンテキストが子リクエストに渡されるため、ファクトリによって作成された子でも共通オブジェクトを再利用できます。

したがって、最終的には、独自のオブジェクトファクトリを使用する必要はありません。

于 2013-01-29T06:33:31.213 に答える