Pregunta

He aplicado mi propia copia del patrón presentador de vista del modelo (en la vena de la fábrica de software cliente web) para que pueda aprovechar mi propio marco DI en lugar de estar atado a ObjectBuilder de WCSF que tuve muchos problemas con. Yo he llegado con un par de maneras de hacerlo, pero ninguno de ellos en particular me hacen feliz. Yo quería saber si alguien más tenía otras ideas.

Solución # 1 bis

Utiliza un HttpModule para interceptar context.PreRequestHandlerExecute llamar ObjectFactory.BuildUp (HttpContext.Current.Handler)

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    private EmployeePresenter Presenter
    {
        set
        {
            _presenter = value;
            _presenter.View = this;
        }
    }
}

Solución # 1b

acumulación de llamadas en la carga de la página en lugar de utilizar un HttpModule

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    private EmployeePresenter Presenter
    {
        set
        {
            _presenter = value;
            _presenter.View = this;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        ObjectFactory.BuildUp(this);
    }
}

Solución # 1c

presentador de acceso a través de la propiedad permite a la acumulación de Getter si es necesario.

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    public EmployeePresenter Presenter
    {
        get
        {
            if (_presenter == null)
            {
                ObjectFactory.BuildUp(this);
            }

            return _presenter;
        }
        set
        {
            _presenter = value;
            _presenter.View = this;
        }
    }
}

Solución # 2

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    private EmployeePresenter Presenter
    {
        get
        {
            if (_presenter == null)
            {
                _presenter = ObjectFactory.GetInstance<EmployeePresenter>();
                _presenter.View = this;
            }

            return _presenter;
        }
    }
}

Solución # 2b

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    private EmployeePresenter Presenter
    {
        get
        {
            if (_presenter == null)
            {
                Presenter = ObjectFactory.GetInstance<EmployeePresenter>();
            }

            return _presenter;
        }
        set
        {
            _presenter = value;
            _presenter.View = this;
        }
    }
}

Editar : Añadido solución 1c, 2b

¿Fue útil?

Solución

que haría uso de la solución # 1b, y crear un supertipo para todas las páginas, con el fin de secar la inicialización presentador de un poco más. de esta manera:

Código de Página:

public partial class _Default : AbstractPage, IEmployeeView
{
    private EmployeePresenter presenter;

    private EmployeePresenter Presenter
    {
        set
        {
            presenter = value;
            presenter.View = this;
        }
    }
    protected override void Do_Load(object sender, EventArgs args)
    {
        //do "on load" stuff 
    }

}

código Página Resumen:

public abstract class AbstractPage : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ObjectFactory.BuildUp(this);
        this.Do_Load(sender,e); 
        //template method, to enable subclasses to mimic "Page_load" event

    }
    //Default Implementation (do nothing)
    protected virtual void Do_Load(object sender, EventArgs e){}
}

Con esta solución tiene la inicialización presentador (creado por el ObjectFactory) en una clase única, si es necesario modificarlo más tarde se puede hacer fácilmente.

Editar

debería ser Do_Load Extracto o Virtual

Método Plantilla principio establece que el método debe ser abstracta, con el fin de obligar a las subclases para implementar que, cumpliendo con el contrato de superclase. (Ver Wikipedia ejemplo de "Monopoly" < "Juego").

Por otro lado, en este caso en particular, no queremos forzar a la clase de usuario para redefinir nuestro método, pero le dan la oportunidad de hacerlo. Si se declara abstracta, muchas clases estarán obligados a redefinir el método que se acaba de dejarlo vacío (esto es claramente un olor de código). Por lo que ofrecen un defecto sensible (no hacer nada) y hacer que el método virtual.

Otros consejos

He construido mi propio marco MVP así también. He encontrado la mejor manera para mí era utilizar los genéricos con una clase de página de base. Especificando el tipo de presentador en la definición de la clase genérica, llego a perder la mayor parte del código que cada una de sus propuestas requiere.

Sin embargo, hay algunas cosas que no me gustan de hacerlo de esa manera. La definición de clase puede terminar encima de parecer bastante complicado, y no es fácil de leer para un novato. Tampoco he completamente elaborado una buena manera de utilizar el modelo de eventos en la página base.

Lo siento, no tengo el código para usted aquí, pero puedo publicar algunos para usted si lo desea. También tengo una versión anterior del código publicado en www.codeplex.com/aspnetmvp, en caso de que desee ver cómo funciona.

He estado usando una clase base con la página:

protected override void OnInit(EventArgs e)
    {
        StructureMap.ObjectFactory.BuildUp(this);
        base.OnInit(e);
    }

El método de la clase base funciona en controles de usuario, así que solo me mantuvo desde el módulo (no quiero tener 2 formas de configurarlo). Para la página es

public partial class Employee : View, IEmployeeView
{
    public ViewPresenter Presenter { get; set; }
    private void Page_Load(object sender, EventArgs e){}
}

I inyecto la vista a través del constructor. Para evitar el problema de referencia circular en la configuración StructureMap, sólo tiene que utilizar este método de ayuda:

static T GetView<T>()
{
    return (T) HttpContext.Current.Handler;
}

En la config StructureMap utilizar una convención tanto para el presentador y la inyección vista.

Gracias a todos por sus comentarios muy valiosos. Sus respuestas cada una me dio ideas valiosas para combinar juntos en mi solución final y esto es lo que ocurrió:

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

    public TPresenter Presenter
    {
        set
        {
            _presenter = value;
            _presenter.View = GetView();
        }
    }

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

    protected override void OnPreInit(EventArgs e)
    {
        ObjectFactory.BuildUp(this);
        base.OnPreInit(e);
    }
}

Y heredado por mi página original:

public partial class _Default : 
    ViewBasePage<EmployeePresenter, IEmployeeView>, IEmployeeView
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            _presenter.OnViewInitialized();
        }

        _presenter.OnViewLoaded();
        Page.DataBind();
    }

    #region Implementation of IEmployeeView

    ...

    #endregion
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top