views:

141

answers:

2
public interface IBasePresenter
{
}
public interface IJobViewPresenter : IBasePresenter
{
}
public interface IActivityViewPresenter : IBasePresenter
{
}

public class BaseView 
{
    public IBasePresenter Presenter
    {
        get;
        set;
    }
}

public class JobView : BaseView
{
    public IJobViewPresenter JobViewPresenter
    {
        get { this.Presenter as IJobViewPresenter;}
    }
}

public class ActivityView : BaseView
{
    public IActivityViewPresenter ActivityViewPresenter
    {
        get { this.Presenter as IActivityViewPresenter;}
    }
}

Lets assume that I need a IBasePresenter property on BaseView. Now this property is inherited by JobView and ActivityView but if I need reference to IJobViewPresenter object in these derived classes then I need to type cast IBasePresenter property to IJobViewPresenter or IActivityPresenter (which I want to avoid) or create JobViewPresenter and ActivityViewPresenter on derived classes (as shown above).

I want to avoid type casting in derived classes and still have reference to IJobViewPresenter or IActivityViewPresenter and still have IBasePresenter in BaseView.

Is there a way I can achieve it ?

+3  A: 

You can do this:

    public class BaseView<TPresenter>
        where TPresenter: IBasePresenter
    {
        TPresenter Presenter { get; set; }
    }

    public class JobView: BaseView<IJobViewPresenter>
    {

    }

If you have code that needs to reference BaseView, you can create an interface and expose the base presenter like this:

    public interface IBaseView
    {
        IBasePresenter BasePresenter { get; }
    }

    public class BaseView<TPresenter> : IBaseView
        where TPresenter: IBasePresenter
    {
        TPresenter Presenter { get; set; }

        IBasePresenter IBaseView.BasePresenter
        {
            get { return Presenter; }
        }
    }

Classes that need access to the BaseView can now consume the interface instead of BaseView directly. You can expose any other base services that need to be consumed in there as well.

Dan Bryant
You can, but there's no need, because the interfaces inherit from each other.
Steven Sudit
@Steven, Could you clarify what you mean by that? I believe the question was how to expose the interface in its derived form, so that it's explicitly clear that the Presenter for a JobView is always an IJobViewPresenter (and not merely casted under the assumption that proper usage will always keep it an IJobViewPresenter.)
Dan Bryant
Nice solution... I like it.. THanks
Deepak
If you have two classes which return two presenters, then just do that, without pretending to be object-oriented. Don't inherit anything.
Steven Sudit
@Steven, I suspect the real code has some common base functionality exposed in BaseView and there are consumers of BaseView which use that functionality to do something. As such there is a benefit to the abstraction.
Dan Bryant
Let me just say that I think you're offering a very good solution, but really, the best thing to do here is to question the premises. If a class has some nice functionality, then by all means use it, but don't inherit from it unless there is a genuine is-a relationship. Deepak's comments about downcasting strongly indicate that such a relationship does not exist, or at the very least, is not healthy.
Steven Sudit
A: 

This is a job for polymorphism.

public interface IBasePresenter
{
}
public interface IJobViewPresenter : IBasePresenter
{
}
public interface IActivityViewPresenter : IBasePresenter
{
}

public class BaseView : IBasePresenter
{
}

public class JobView : BaseView, IJobViewPresenter
{
}

public class ActivityView : BaseView, IActivityViewPresenter
{
}
Steven Sudit
This assumes the views implement the view presenter, whereas the original post has the views containing view presenters.
Dan Bryant
@Dan: I guess the point is that I'm objecting to the constraints. I don't think the child classes ought to return child interfaces. It pretty much removes any point to having an inheritance structure.
Steven Sudit