2016-09-21 7 views
0

私たちはマシンオートメーションソフトウェアにNinject依存関係注入を使用しており、循環参照に問題があります。衝突を避けるために、互いに認識しておく必要のあるいくつかの物理的なオブジェクトがあります。各動作を許可するCollisionHandlerクラスを追加しました。例:ロボットアームは、ハッチが移動する前に開いていることを確認します。そして、ハッチは、ロボットアームが閉まる前に途中であることをチェックします。遅れたNinjectセッターメソッドの注入

ロボットと衝突ハンドラだけでNinject setter method injection patternの概念実証テストを行いました。これでうまくいきました。最初にロボットが作成され、次にCollisionHandlerと最後に注射メソッドがRobotに呼び出されました。ロボット、ハッチとCollisionHandler両方がシングルトンとしてバインドされています

Bind<Robot>().ToSelf().InSingletonScope() 
Bind<Hatch>().ToSelf().InSingletonScope() 
Bind<CollisionHandler>().ToSelf().InSingletonScope() 

public class Robot 
{ 
    private CollisionHandler _collisionHandler; 

    public Robot(ISomeService someService) 
    { 
    } 

    [Inject] 
    public void PostConstructInject(CollisionHandler collisionHandler) 
    { 
     if (_collisionHandler != null) 
      throw new InvalidOperationException("PostConstructInject called more than once"); 
     _collisionHandler = collisionHandler; 
    } 
} 

public class CollisionHandler 
{ 
    private readonly Robot _robot; 
    private readonly Hatch _hatch; 

    public CollisionHandler(Robot robot, Hatch hatch) 
    { 
     _robot = robot; 
     _hatch = hatch; 
    } 

    public bool IsRobotAwayFromHatch() { } 
    public bool IsHatchOpen() { } 
} 

すべて私が他のエンティティのためのパターンを実装するに移っ罰金見えました。それが働いていない場所です。

Activation path: 
4) Injection of dependency CollisionHandler into parameter collisionHandler of method PostConstructInjection of type Robot 
3) Injection of dependency Robot into parameter robot of constructor of type CollisionHandler 
2) Injection of dependency CollisionHandler into parameter collisionHandler of method PostConstructInjection of type Hatch 
1) Request for Hatch 

public class Hatch 
{ 
    private CollisionHandler _collisionHandler; 

    public Hatch(ISomeOtherService someOtherService) 
    { 
    } 

    [Inject] 
    public void PostConstructInject(CollisionHandler collisionHandler) 
    { 
     if (_collisionHandler != null) 
      throw new InvalidOperationException("PostConstructInject called more than once"); 
     _collisionHandler = collisionHandler; 
    } 
} 

問題はNinjectがオブジェクトを作成した後に直接注入メソッドを呼び出すために望んでいることである:ハッチに注入する方法の追加、Ninjectはもはやオブジェクトグラフを構築することができません

Robot robot = new Robot(someService); 
robot.PostConstructInject(/* We need a CollisionHandler instance before it is constructed */); 
Hatch hatch = new Hatch(someOtherService); 
CollisionHandler collisionHandler = new CollisionHandler(robot, hatch); 
hatch.PostConstructInject(collisionHandler); 

私はそれがやりたいことはPostConstructInjectがCollisionHandlerインスタンスがCREされた後に呼び出しを移動することです。これは、次のコードに等しいですated:

Robot robot = new Robot(someService); 
Hatch hatch = new Hatch(someOtherService); 
CollisionHandler collisionHandler = new CollisionHandler(robot, hatch); 
robot.PostConstructInject(collisionHandler); 
hatch.PostConstructInject(collisionHandler); 

Ninjectに可能な限り注入メソッドを呼び出さないようにする方法はありますか?私は[Inject]属性を削除してCollisionHandlerにそれらのメソッドを呼び出させることができますが、それはかなり醜いと感じます。

+0

私は、個々のコンポーネントがシステムを駆動するのではなく、プロセス全体を編成するアプローチが必要だと思います。ハッチとアームはお互いを気にしてはいけません。特定のことがあり、これを処理するのはオーケストレーター(おそらくロボットクラス)です。これは、コンポーネントがシンプルで堅牢で、責任を分けることができるため、良いことです。 –

答えて

1

これを行う方法があります。しかし、一般的に、このような循環的な依存関係がある場合は、設計上の間違った方向にいることになります。サイクリック依存関係を持つ正当な理由はほとんどありません。インスタンスを構築するだけでなく、多くのことをもっと複雑にします。あなたは簡単に維持するのが難しい完全にもつれたデザインで終わるでしょう。

私の警告にもかかわらず、このパスに従うには、Lazyの工場拡張とサポートを参照するよりも、私は本当にこれは良いデザインではないと思うので、私はあなたに多くのヒントを与えることはありません。

関連する問題