2012-04-30 12 views
7

Ich habe das MVP-Muster in einigen WinForms-Anwendungen implementiert, die eine passive Ansicht verwenden. Ich implementiere eine Schnittstelle, die Eigenschaften und Stellvertreter in Form von Aktion < T> und Func < T> enthält, um UI-Ereignisse in konkreten Ansichten zu verkabeln und zum Präsentator zurückzurufen.MVP, Winforms - EventHandlers oder Delegaten

Ich bin im Begriff, ein neues Projekt zu starten und habe ein wenig Forschung in das Muster online einschließlich der vielen Beispiele des Musters hier und beachten Sie, dass alle EventHandler verwenden, um Moderatoren zu benachrichtigen.

Ich verstehe nicht wirklich, warum Ereignisse in diesem Fall verwendet werden würden, da ich eine Ansicht als nur einen Präsentator sehen.

Meine Frage ist, ist dies aus Gründen der Konsistenz mit dem, wie das .Net-Framework Ereignisse verwendet, oder aus einem anderen Grund, den ich nicht sehe? Hier

ist ein triviales Beispiel des Musters ich benutze:

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

Antwort

4

Ihr Muster ist im Wesentlichen der gleiche wie Ereignisse mit, mit einem entscheidenden Unterschied. Ereignisse stellen den zugrunde liegenden Delegaten nicht zur Verfügung (ModelDataChangedCallback in Ihrem Beispiel). Dies zu offenbaren, ist eine schlechte Übung, da anderer Code beispielsweise die Aufrufliste löschen kann. Ein Ereignis hat einen zugrunde liegenden Delegaten, der hinzugefügt oder entfernt werden kann, aber nie außerhalb des Bereichs der Klasse gelöscht werden kann.

Ich verstehe nicht Ihren Punkt über nicht mehrere Abonnenten - das ist kein Grund, keine Ereignisse zu verwenden. Ein Ereignis ist nur eine Möglichkeit für eine Klasse zu sagen "Hey! Das ist passiert", eine 1-zu-1-Zuordnung mit einem Presenter-Objekt ist völlig in Ordnung und normal.

Sie enden auch nicht mit dieser ziemlich merkwürdigen Schreibeigenschaft in der Ansicht.

+0

Vereinbart mit den Nur-Schreib-Eigenschaften, es stört mich, wenn ich sie sehe, und fügt mehr Standardcode hinzu, als ich für komplexe Ansichten haben möchte. –

+0

Aber wenn er ein Ereignis benutzt, müsste er eine spezifische 'ModelDataChangedEventArgs' Klasse erstellen, nur um die Daten zu enthalten, mit denen der Presenter arbeiten muss, richtig? Bei vielen Ereignissen wird die Anzahl der Kesselplattenklassen explodieren. Alle 'Aktion MyDelegate' muss in 'EventHandler MyEvent' geändert werden ... Da es sich um ein 1: 1 Mapping handelt, sollte die Wahrscheinlichkeit, dass jemand die Aufrufliste löscht, sehr begrenzt sein ... –