środa, 8 marca 2017

CQRS część 3 - Event, Consumer

Hej,
wracamy do naszego CQRSa. Omówiłem już jego dwa podstawowe elementy czyli Komendy i Zapytania i na tym teoretycznie sam wzorzec poprzestaje, jednak oglądając na githubie jego różne implementacje zdecydowałem dołożyć do niego te dwa przydatne elementy. Zdarzenia są oczywiście wywoływane tylko przez handlery komend bo tylko tam zmieniamy stan systemu. Przenosząc się z Flexa do Xamarina, naturalne były dla mnie Eventy - we Flexie są bardzo dobrze zaimplementowane, a ich propagacja w systemie, propagacja po drzewie renderingu w górę do korzenia, anulowanie itp były out of the box. Zmieniłem z tego powodu trochę konwencję nazewnictwa samych zdarzeń co zobaczycie za chwilkę w snippetach. Konsument - jest to interfejs, który implementują klasy nasłuchujące na zdarzenia - zazwyczaj modele widoków. Wstęp za nami, lecimy z kodem, marker interface dla zdarzeń:

public interface IEvent
{
}

I od razu nasz interfejs szyny zdarzeń, dla mojej wygody po przesiadce z Flexa zamiast IEventBus interfejs po którym odnajdujemy w kontenerze naszą szynę nazywa się tak:

public interface IEventPublisher
{
    Task PublishAsync<TEvent>(TEvent @event) where TEvent : IEvent;
    void RegisterAsyncConsumer<TEvent>(IConsumerAsync<TEvent> consumer) where TEvent : IEvent;
    void UnregisterAsyncConsumer<TEvent>(IConsumerAsync<TEvent> consumer) where TEvent : IEvent;
}

Musicie mi wybaczyć tą zmianę konwencji nazewnictwa, sama klasa implementująca nazywa się już poprawnie :) Jak widać z samego interfejsu - wszystkie eventy obsługiwane są asynchronicznie - z początku chciałem zrobić dwie ścieżki tak jak dla komend jednak uznałem to za zbędną komplikacje i zostało mi to co widać. Nie będę zamieszczał tym razem implementacji gdyż jest trywialna (jest na githubie) i opiera się na jednym polu zawierającym typ eventa i listę instancji klas nasłuchujących, które niestety musiałem zapakować w object:

private static Dictionary<Type, List<object>> _consumersAsync = new Dictionary<Type, List<object>>();

Dla konsumenta przygotowałem interfejs:

public interface IConsumerAsync<TEvent> where TEvent : IEvent
{
    Task HandleAsync(TEvent eventMessage);
}

Ponieważ spora część moich zdarzeń do będą CRUDowe informacje na temat dodania, aktualizacji lub usunięcia elementu dodałem bardzo przydatną uniwersalną klasę generyczną:

public class Event<TData> : IEvent where TData : DataModelBase
{
    public TData Item { get; protected set; }

    public EventAction Action { get; protected set; }

    public Event(TData item, EventAction action)
    {
        this.Action = action;
        this.Item = item;
    }
}

public enum EventAction
{
    CREATE = 1,
    UPDATE= 2,
    DELETE = 3
}

Kolejna porcja mojego CQRSa za nami, jeszcze trochę do omówienia zostało ale to w kolejnych postach, do przeczytania jutro!

1 komentarze:

yanzak pisze...

Betway Casino Login (login-only) | jtmhub.com
The official Betway Casino Login page. · Login Page. 전라남도 출장안마 To access the page, 파주 출장안마 press the 제천 출장샵 "PLAY NOW" key. · Once 하남 출장마사지 the user login, 나주 출장마사지 you'll