Search code examples
c#asp.netgenericswebformspage-lifecycle

ASP.NET BasePage back referencing to concrete implementation


I have a page that is setup like this

public partial class _Default : ViewBasePage<EmployeePresenter, IEmployeeView>,
                                 IEmployeeView
{
...
}

Inside my base page

public abstract class ViewBasePage<TPresenter, TView> : 
        Page where TPresenter : Presenter<TView> where TView : IView
{
    protected TPresenter _presenter;

    public TPresenter Presenter
    {
        set
        {
            _presenter = value;
            _presenter.View = GetView(); // <- Works
            //_presenter.View = (TView)this; <- Doesn't work
        }
    }

    /// <summary>
    /// Gets the view. This will get the page during the ASP.NET
    /// life cycle where the physical page inherits the view
    /// </summary>
    /// <returns></returns>
    private static TView GetView()
    {
        return (TView) HttpContext.Current.Handler;
    }
}

What I need to do is actually cast (TView)_Default, using my GetView() method does indeed end with that result. Inside the base page I can't do

_presenter.View = (TView)this;

Because this is actually ViewBasePage<TPresenter,TView> so it can't directly cast to just TView.

So my actual question is there any alternative ways to achieve my result in a way that feels less hacky, if this is the primary option is there really anything I need to be concerned about by treating my page in this manner?

Edit:

The exact part I'm trying to write away is

private static TView GetView()
{
    return (TView) HttpContext.Current.Handler;
}

as I feel like this is fairly gross hack to be able to reference back to the page in this context.


Solution

  • I don't see how (TView)this is expected to work. this is referring to the class which happens to be a Page. You can't convert a Page to an IView.

    Your current implementation doesn't look at all hacky.

    Am I missing something?

    EDIT: now that I understand your situation a little better; what about having ViewBasePage inherit from IView (And removing it from your _Default page)?

    EDIT Furthermore, if you then want the _Default page to have to implement the functions defined in the Interface, you can have the ViewBasePage class implement the interface's functions abstractly.

    public class _Default : ViewBasePage<Presenter<IView>, IView>
    {
        #region Overrides of classB
        public override void test()
        {
            //perform the test steps.
        }
        #endregion
    }
    public abstract class ViewBasePage<TPresenter, TView> :
        Page, IView
        where TPresenter : Presenter<TView>
        where TView : IView
    {
        protected TPresenter _presenter;
    
        public TPresenter Presenter
        {
            set
            {
                _presenter = value;
                _presenter.View = (TView)((IView)this); //<- Now it does work
            }
        }
        #region Implementation of IView
        public abstract void test();
        #endregion
    }
    public interface IView
    {
        void test();
    }
    public abstract class Presenter<TView> where TView : IView
    {
        public TView View { get; set; }
        public virtual void OnViewInitialized(){}
        public virtual void OnViewLoaded(){}
    }