tags:

views:

157

answers:

3

As an experiment I'm trying to write a generic MVP framework.

I started with:

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

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

Obviously this can't work because the types of TView and TPresenter can't be resolved. You'd be writing Type<Type<... forever. So my next attempt looked like this:

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

public interface IView:IView<IPresenter>
{

}

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

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

This actually compiles and you can even inherit from these interfaces like so:

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

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

The problem is in the class definition you have to define any members declared in the generic type twice. Not ideal but it still compiles. The problem's start creeping up when you actually try to access the members of a Presenter from a View or vice versa. You get an Ambiguous reference when you try to compile. Is there any way to avoid this double implementation of a member when you inherit from both interfaces? Is it even possible to resolve two mutually dependent generic types at compile time?

+2  A: 

This compiles, but I'm not certain it's the route to go.

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>
{
}
Scott J
+2  A: 

I think the problem here is that you shouldn't need both the IView and IPresenter interfaces to be generic - in an MVP framework either the view should call the presenter directly to drive the form (in which case the view should be generic for some presenter type) or the view should be totally unaware of the presenter and communicate through events (in which case the presenter should be generic for a particular view type).

Lee
Exactly. I was just putting together "passive view" framework in C++, and the only component that really needs to be a template is the base presenter, IPresenter<T> where T is the particular view type.class MyPresenter : protected IPresenter<MyView> {}
kert
A: 

Your view should take the type of your model, say TModel. The presenter should take a type of TView. I don't think there should be a TPresenter.

Richard Hein