2012-04-30 9 views
7

Implementé el patrón MVP en algunas aplicaciones de WinForms que usan una vista pasiva. Implemento una interfaz que contiene propiedades y delegaciones en forma de Acción < T> y Func < T> para conectar los eventos de IU en vistas concretas y devolver la llamada al presentador.MVP, Winforms - EventHandlers o Delegados

Estoy a punto de comenzar un nuevo proyecto e investigué un poco sobre el patrón en línea, incluidos los muchos ejemplos del patrón aquí, y noté que todos usaban EventHandler para notificar a los presentadores.

Realmente no entiendo por qué los eventos se utilizarían en este caso, ya que veo una vista como solo tener un presentador.

Mi pregunta es, ¿esto es por el bien de seguir siendo coherente con la forma en que el .Net Framework usa eventos, o por alguna otra razón que no estoy viendo?

Aquí es un ejemplo trivial de la pauta que utilizo:

public interface IViewAbstraction 
{ 
    public ModelData ModelData { set; } 
    public Action<ModelData> ModelDataChangedCallback { set; } 
} 

public class SomeWinForm : Form, IViewAbstraction 
{ 
    private Action<ModelData> modelDataChanged; 
    private ModelData model; 

    public ModelData ModelData 
    { 
     set { /* when this property changes, update UI */ } 
    } 

    public Action<ModelData> ModelDataChangedCallback 
    { 
     set { modelDataChanged = value; } 
    } 

    private void OnSomeWinformsEvent(EventArgs args) 
    { 
     if (modelDataChanged == null) throw new Exception(); 

     modelDataChanged(model); 
    } 
} 

public class Presenter 
{ 
    private readonly IViewAbstraction view; 
    private readonly IDataLayerAbstraction dataLayer; 

    public Presenter(IViewAbstraction view, IDataLayerAbstraction dataLayer) 
    { 
     this.dataLayer = dataLayer; 
     this.view = view; 
     this.view.ModelDataChangedCallback = OnModelChanged; 
     this.view.ModelData = dataLayer.GetData(); 
    } 

    private void OnModelChanged(ModelData data) 
    { 
     // validate and save data. 
    } 
} 

Respuesta

4

Su patrón es esencialmente el mismo que el uso de eventos, con una diferencia clave. Los eventos no exponen el delegado subyacente (ModelDataChangedCallback en su ejemplo). Exponer esto es una mala práctica ya que otro código puede borrar la lista de invocación, por ejemplo. Un evento tendrá un delegado subyacente que se puede agregar o eliminar, pero que nunca se borrará fuera del alcance de la clase.

No entiendo su punto acerca de no tener múltiples suscriptores: esta no es una razón para no usar eventos. Un evento es solo una manera para que una clase diga "Oye, esto ha sucedido", una asignación de 1 a 1 con un objeto de Presenter es perfectamente razonable y normal.

También no termina con esa propiedad de escritura de aspecto bastante extraño en la vista.

+0

Estoy de acuerdo con las propiedades solo de escritura, me molesta cuando las veo y agrega más código repetitivo de lo que me gustaría para vistas complejas. –

+0

Pero al usar un evento, debería crear una clase específica 'ModelDataChangedEventArgs' solo para contener los datos con los que el presentador necesita trabajar, ¿no? Cuando hay muchos eventos, se verá la cantidad de clases de placas de calderas. Toda la 'Acción MyDelegate' tiene que cambiarse a' EventHandler MyEvent' ... Dado que es una asignación 1: 1, la probabilidad de que alguien borre la lista de invocación debería ser muy limitada ... –