2012-04-30 12 views
7

Zaimplementowałem wzorzec MVP w kilku aplikacjach WinForm, które używają widoku pasywnego. Implementuję interfejs zawierający właściwości i delegatów w postaci akcji < T> i Func < T>, aby połączyć zdarzenia UI w konkretnych widokach i oddzwonić do prezentera.MVP, WinForm - EventHandlers lub Delegaci

Mam zamiar rozpocząć nowy projekt i trochę zbadać wzór online, w tym wiele przykładów wzoru tutaj i zauważyć, że wszystkie używają EventHandler do powiadamiania prezenterów.

Nie do końca rozumiem, dlaczego w tym przypadku użyto zdarzeń, ponieważ widzę widok tylko jako jeden prezenter.

Moje pytanie brzmi, czy jest to ze względu na zachowanie spójności z tym, jak środowisko .Net wykorzystuje zdarzenia, czy z innego powodu, którego nie widzę?

Tutaj jest trywialny przykład wzorca używam:

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

Odpowiedz

4

Twój wzór jest zasadniczo taki sam, jak przy użyciu zdarzenia, z jedną istotną różnicą. Zdarzenia nie wystawiają podstawowej delegaty (ModelDataChangedCallback w twoim przykładzie). Ujawnienie tego jest złą praktyką, ponieważ inny kod może na przykład wyczyścić listę wywołań. Wydarzenie będzie miało delegata bazowego, do którego można dodawać lub usuwać, ale nigdy nie można go usunąć poza zakresem zajęć.

Nie rozumiem, że nie masz wielu subskrybentów - nie jest to powód, aby nie używać wydarzeń. Wydarzenie jest po prostu sposobem, by klasa powiedziała: "Hej, to się stało", mapowanie 1 na 1 z obiektem Presenter jest całkowicie rozsądne i normalne.

Nie kończy się również na tym raczej dziwnym obiekcie w widoku tylko do zapisu.

+0

Uzgodnione na właściwości tylko do zapisu, budzi mnie, gdy widzę je i dodaje więcej kodu standardowego niż chciałbym dla złożonych widoków. –

+0

Ale przy korzystaniu z eventu musiałby stworzyć specyficzną klasę 'ModelDataChangedEventArgs' tylko po to, aby pomieścić dane, z którymi Presenter musi pracować, prawda? W przypadku dużej liczby zdarzeń, liczba klas płyt kotła zostanie usunięta. Wszystkie 'Action MyDelegate' należy zmienić na' EventHandler MyEvent' ... Ponieważ jest to mapowanie 1: 1, prawdopodobieństwo, że ktoś wyczyści listę wywołań, powinno być bardzo ograniczone ... –