2010-03-19 3 views
3

À titre expérimental, j'essaie d'écrire un cadre générique MVP.C# Fun avec les génériques - les dépendances mutuelles

J'ai commencé avec:

public interface IPresenter<TView> where TView: IView<IPresenter<... 
{ 
    TView View { get; set;} 
} 

public interface IView<TPresenter> where TPresenter:IPresenter<IView<... 
{ 
    TPresenter Presenter { get; set; } 
} 

Évidemment, cela ne peut pas fonctionner parce que les types de TView et TPresenter ne peuvent être résolus. Vous écririez Type<Type<... pour toujours. Donc, ma prochaine tentative ressemblait à ceci:

public interface IView<T> where T:IPresenter 
{ 
    ... 
} 

public interface IView:IView<IPresenter> 
{ 

} 

public interface IPresenter<TView> where TView: IView 
{ 
    ... 
} 

public interface IPresenter: IPresenter<IView> 
{ 
    ... 
} 

Cette compile en fait et vous pouvez même hériter de ces interfaces comme ceci:

public class MyView : IView, IView<MyPresenter> 
{ 
    ... 
} 

public class MyPresenter : IPresenter, IPresenter<MyView> 
{ 
    ... 
} 

Le problème est dans la définition de la classe, vous devez définir tous les membres déclarés dans le type générique deux fois. Pas idéal mais il compile encore. Le problème commence à grimper lorsque vous essayez d'accéder aux membres d'un présentateur à partir d'une vue ou vice versa. Vous obtenez une référence ambiguë lorsque vous essayez de compiler. Est-il possible d'éviter cette double implémentation d'un membre lorsque vous héritez des deux interfaces? Est-il même possible de résoudre deux types génériques mutuellement dépendants au moment de la compilation?

Répondre

2

Je pense que le problème ici est que vous ne devriez pas besoin à la fois les interfaces IView et IPresenter être générique - dans un cadre MVP soit le point de vue devrait appeler le présentateur directement à conduire la forme (auquel cas la vue doit être générique pour un type de présentateur) ou la vue doit être totalement ignorante du présentateur et communiquer à travers les événements (dans ce cas, le présentateur doit être générique pour un type de vue particulier).

+0

Exactement. Je ne faisais que mettre en place un framework de "vue passive" en C++, et le seul composant qui doit vraiment être un template est le présentateur de base, IPresenter où T est le type de vue particulier. class MyPresenter: protected IPresenter {} – kert

3

Cela compile, mais je ne suis pas certain que ce soit la voie à suivre.

public interface IPresenter<P, V> 
    where P : IPresenter<P, V> 
    where V : IView<P, V> 
{ 
} 

public interface IView<P, V> 
    where P : IPresenter<P, V> 
    where V : IView<P, V> 
{ 
} 

public class MyView : IView<MyPresenter, MyView> 
{ 
} 

public class MyPresenter : IPresenter<MyPresenter, MyView> 
{ 
} 
0

Votre avis devrait prendre le type de votre modèle, disons TModel. Le présentateur devrait prendre un type de TView. Je ne pense pas qu'il devrait y avoir un TPresenter.

Questions connexes