2016-09-21 85 views
0

我們對機器自動化軟件使用Ninject依賴注入,並遇到循環引用的問題。我們有幾個物理對象需要相互瞭解以避免碰撞。我們添加了一個授權每個動作的CollisionHandler類。例如:機器人手臂在通過之前檢查艙口是否打開。在關閉之前,艙口蓋檢查機器人手臂是否擋住了路。延遲Ninject setter方法注入

我只用機器人和碰撞處理程序進行了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() { } 
} 

這一切看上去都不錯,所以我轉移到實施的其他實體的模式。這就是停止工作的地方。添加註射的方法來孵化,Ninject不再能夠構建對象圖:

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要構造對象後直接調用注射方法:

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 

這相當於下面的代碼:

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

有辦法做到這一點。但是一般情況下,如果你有這樣的循環依賴關係,那麼你的設計就走錯了路。有循環依賴幾乎沒有好理由。它們使得許多事情變得複雜得多,不僅僅是建立你的實例。您將很容易得到一個難以維護的完全糾結的設計。

如果你真的想遵循這條路徑,儘管我的警告,而不是看看工廠擴展和支持懶惰。我不會給你更多的提示,因爲我真的認爲這不是一個好設計。