2010-04-01 45 views
2

我正嘗試在我的MVP應用程序中使用Ninject進行依賴注入。然而,我有一個問題,因爲我有兩種類型相互依賴,從而創建一個循環依賴。起初,我明白這是一個問題,因爲我有兩種類型在構造函數中需要彼此。因此,我將其中一個依賴項移到了屬性注入中,但我仍然收到錯誤消息。我究竟做錯了什麼?解決Ninject中的循環依賴(Compact Framework)

這是主持人:

public class LoginPresenter : Presenter<ILoginView>, ILoginPresenter 
{ 
    private ISettings _settings; 
    private IViewProvider _viewProvider; 
    private IDataProvider _dataProvider; 

    public LoginPresenter(
     ILoginView view, 
     ISettings settings, 
     IViewProvider viewProvider, 
     IDataProvider dataProvider) 
     : base(view) 
    { 
     _settings = settings; 
     _viewProvider = viewProvider; 
     _dataProvider = dataProvider; 
    } 
} 

和本所認爲:

public partial class LoginForm : Form, ILoginView 
{ 
    [Inject] 
    public ILoginPresenter Presenter { private get; set; } 

    public LoginForm() 
    { 
     InitializeComponent(); 
    } 
} 

下面是導致異常的代碼:

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [MTAThread] 
    static void Main() 
    { 
     // Show the login form 
     Views.LoginForm loginForm = Kernel.Get<Views.Interfaces.ILoginView>() as Views.LoginForm; 
     Application.Run(loginForm); 
    } 
} 

唯一的例外發生在與Kernel.Get<>()通話。那就是:

Error activating ILoginPresenter using binding from ILoginPresenter to LoginPresenter 
A cyclical dependency was detected between the constructors of two services. 

Activation path: 
    4) Injection of dependency ILoginPresenter into property Presenter of type LoginForm 
    3) Injection of dependency ILoginView into parameter view of constructor of type LoginPresenter 
    2) Injection of dependency ILoginPresenter into property Presenter of type LoginForm 
    1) Request for ILoginView 

Suggestions: 
    1) Ensure that you have not declared a dependency for ILoginPresenter on any implementations of the service. 
    2) Consider combining the services into a single one to remove the cycle. 
    3) Use property injection instead of constructor injection, and implement IInitializable 
    if you need initialization logic to be run after property values have been injected. 

爲什麼不Ninject明白,因爲一個是構造函數注入,另一個是財產注射,這樣可以工作得很好?我甚至在某處尋找解決這個問題的方法,只要循環依賴不在構造函數中,Ninject就可以得到這個正確的答案。但顯然不是。任何幫助解決這個將不勝感激。

根據維基百科,視圖手動實例化其具體演示者是很常見的,但我不能這樣做,因爲您可以看到,演示者還需要解決其他依賴關係。

回答

0

我 「繞」 的問題通過創建 「PresenterProvider」:

public interface IPresenterProvider 
{ 
    P Get<P, V>(V view) 
     where V : IView 
     where P : IPresenter<V>; 
} 

public class PresenterProvider : IPresenterProvider 
{ 
    private IKernel _kernel; 

    public PresenterProvider(IKernel kernel) 
    { 
     _kernel = kernel; 
    } 

    #region IPresenterProvider Members 

    public P Get<P, V>(V view) 
     where P : IPresenter<V> 
     where V : IView 
    { 
     return _kernel.Get<P>(new ConstructorArgument("view", view)); 
    } 

    #endregion 
} 

然後,在視圖中我這樣做:

public partial class LoginForm : Form, ILoginView 
{ 
    private ILoginPresenter _presenter; 

    public LoginForm(IPresenterProvider presenterProvider) 
    { 
     InitializeComponent(); 
     _presenter = presenterProvider.Get<ILoginPresenter, ILoginView>(this); 
    } 
} 

主講保持不變。這樣,我手動「解決」循環依賴。當然,更好的建議仍然值得歡迎。