2012-04-30 15 views
7

Ho implementato il pattern MVP in alcune applicazioni WinForms che utilizzano una vista passiva. Implemento un'interfaccia contenente proprietà e delegati sotto forma di Azione < T> e Func < T> per collegare eventi UI in viste concrete e richiamare il presentatore.MVP, Winforms - EventHandlers o Delegati

Sto per iniziare un nuovo progetto e ho fatto una piccola ricerca sul modello online inclusi i molti esempi del modello qui e ho notato che tutti usano EventHandler per notificare i presentatori.

Non capisco veramente perché gli eventi verrebbero utilizzati in questo caso, poiché vedo una vista come se avessi solo un presentatore.

La mia domanda è, è questo per rimanere coerente con il modo in cui il framework .Net utilizza eventi o per qualche altra ragione che non vedo?

Ecco un esempio banale del pattern che uso:

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. 
    } 
} 

risposta

4

il vostro modello è essenzialmente lo stesso che utilizzare gli eventi, con una differenza fondamentale. Gli eventi non espongono il delegato sottostante (ModelDataChangedCallback nell'esempio). L'esposizione di questo è una cattiva pratica, poiché un altro codice può cancellare la lista di chiamate, ad esempio. Un evento avrà un delegato sottostante che può essere aggiunto o rimosso da, ma mai cancellato dall'esterno della classe.

Non capisco il tuo punto di non avere più abbonati - questo non è un motivo per non usare gli eventi. Un evento è solo un modo per una classe di dire "Ehi, questa cosa è successo", una mappatura 1-a-1 con un oggetto Presenter è perfettamente ragionevole e normale.

Non si finisce con quella proprietà di sola scrittura dall'aspetto piuttosto strano nella vista.

+0

Concordato sulle proprietà di sola scrittura, mi infastidisce quando li vedo e aggiunge più codice boilerplate di quanto mi piacerebbe per viste complesse. –

+0

Ma quando si usa un evento, dovrebbe creare una specifica classe 'ModelDataChangedEventArgs' solo per contenere i dati con i quali il Presenter deve lavorare, giusto? Quando ci sono molti eventi, il numero di classi di piastre per caldaie esploderà. Tutto l'azione " MyDelegate' deve essere modificata in" EventHandler MyEvent' ... Poiché si tratta di un mapping 1: 1, la probabilità che qualcuno cancelli l'elenco di chiamata dovrebbe essere molto limitata ... –