Skip to content

sfmohassel/libc.eventbus

Repository files navigation

An in-memory event aggregator without any dependency

Why bother?

In Domain-Driven Design (DDD) pattern, there are times when we want to inform other parts of application about occurrence of an event. This is the primary goal of DOMAIN EVENTS

Read More

You can checkout my article on EventAggregator HERE

Installation

The package is available on nuget.org:

PM> Install-Package libc.eventbus

Simple Usage

Let's say we have a simple message event that has a text:

public class SimpleMessage : IEvent {
    public string Text { get; private set; }

    public SimpleMessage(string text) {
        Text = text;
    }
}

Now we want that when a SimpleMessage is raised, print it in two distinct ways:

public class PrintMessageRaw : IEventHandler<SimpleMessage> {
    public Task Handle(SimpleMessage ev) {
        // print message
        Console.WriteLine($"Raw: {ev.Text}");
        return Task.CompletedTask;
    }
}

public class PrintMessagePretty : IEventHandler<SimpleMessage> {
    public Task Handle(SimpleMessage ev) {
        // print message
        Console.WriteLine($"Pretty: {ev.Text}");
        return Task.CompletedTask;
    }
}

As you can see both PrintMessageRaw and PrintMessagePretty implement IEventHandler<SimpleMessage>.

Put it together

Read the comments please

public void Showcase_WithoutCatchAll() {
    // 1- create an event bus
    var bus = new DefaultEventBus();

    // 2- subscribe to SimpleMessage event via PrintMessageRaw event handler
    bus.Subscribe<SimpleMessage, PrintMessageRaw>(new PrintMessageRaw());

    // 3- subscribe to SimpleMessage event via PrintMessagePretty event handler
    var x = new PrintMessagePretty();
    bus.Subscribe<SimpleMessage, PrintMessagePretty>(x);

    // 4- remember subscribing to a message with the same handler instance, has no effect!
    bus.Subscribe<SimpleMessage, PrintMessagePretty>(x);

    // 5- create the event
    var message = new SimpleMessage("a simple message");

    // 6- publish the event
    bus.Publish(message);
}

The console will show:

Raw: a simple message
Pretty: a simple message

Usage 2

There are times that we need to catch all the event (for example for logging purposes). There's a ICatchAllEventHandler interface that you can register in the bus. To test it, first add a new event:

public class PrivateMessage : IEvent {
    public string Secret { get; private set; }

    public PrivateMessage(string secret) {
        Secret = secret;
    }
}

then an implementation of ICatchAllEventHandler:

public class CatchAllMessages : ICatchAllEventHandler {
    public Task Handle(IEvent ev) {
        if (ev is SimpleMessage) {
            Console.WriteLine($"Caught SimpleMessage: {(ev as SimpleMessage).Text}");
        } else if (ev is PrivateMessage) {
            Console.WriteLine($"Caught PrivateMessage: {(ev as PrivateMessage).Secret}");
        }
        return Task.CompletedTask;
    }
}

Put it together

Read the comments please

public void Showcase_WithCatchAll() {
    // 1- create an event bus
    var bus = new DefaultEventBus();

    // 2- subscribe to SimpleMessage event via PrintMessageRaw event handler
    bus.Subscribe<SimpleMessage, PrintMessageRaw>(new PrintMessageRaw());

    // 3- subscribe to SimpleMessage event via PrintMessagePretty event handler
    bus.Subscribe<SimpleMessage, PrintMessagePretty>(new PrintMessagePretty());

    // 4- register a catch-all event handler
    bus.RegisterCatchAllHandler(new CatchAllMessages());

    // 5- create the event
    var message = new SimpleMessage("a simple message");

    // 6- publish the event
    bus.Publish(message);
}

The console will show:

Raw: a simple message
Pretty: a simple message
Caught SimpleMessage: a simple message

To see the full showcase click here

Contributions are welcome