2010-04-01 5 views
2

J'essaie d'utiliser Ninject pour l'injection de dépendances dans mon application MVP. Cependant, j'ai un problème car j'ai deux types qui dépendent les uns des autres, créant ainsi une dépendance cyclique. Au début, je comprends que c'était un problème, parce que j'avais les deux types nécessitent l'un l'autre dans leurs constructeurs. Par conséquent, j'ai déplacé une des dépendances à une injection de propriété à la place, mais je reçois toujours le message d'erreur. Qu'est-ce que je fais mal?Résolution d'une dépendance cyclique dans Ninject (Compact Framework)

C'est le présentateur:

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; 
    } 
} 

et est la vue:

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

    public LoginForm() 
    { 
     InitializeComponent(); 
    } 
} 

Et voici le code qui fait l'exception:

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); 
    } 
} 

L'exception se produit sur la ligne avec l'appel Kernel.Get<>(). Ici, il est:

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. 

Pourquoi ne pas Ninject comprendre que depuis une injection est constructeur et l'autre est l'injection de propriété, cela peut très bien fonctionner? J'ai même lu quelque part à la recherche de la solution à ce problème que Ninject aurait supposé avoir raison tant que la dépendance cyclique n'est pas à la fois dans les constructeurs. Apparemment non, cependant. Toute aide pour résoudre ce problème serait très appréciée. Selon Wikipédia, il est courant que la vue instancie manuellement son présentateur concret, mais je ne peux pas le faire dans mon cas car, comme vous pouvez le voir, le présentateur a d'autres dépendances qui doivent être résolues.

Répondre

0

j'ai eu "autour" du problème en créant un "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 
} 

Puis, dans la vue que je fais ceci:

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

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

Le présentateur reste le même. De cette façon, je "résous" la dépendance cyclique manuellement. De meilleures suggestions sont toujours les bienvenues, bien sûr.