Click here to Skip to main content
15,886,873 members
Articles / Programming Languages / C#

EventAggregator - My Take

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
21 Jan 2024CPOL2 min read 3.6K   78   3   9
A dead simple message passing framework
The EventAggregator framework enables communication between loosely coupled components using an event mechanism. This article will discuss the inner workings of this simple implementation of the EventAggregator.

Introduction

The EventAggregator framework enables communication between loosely coupled components using an event mechanism. This article will discuss the inner workings of this simple implementation of the EventAggregator.

In the past, I've used the EventAggregator implementation provided by Prism, but unlike the Prism implementation, this version has less of a footprint and is Open Source.

At this point, I should admit that I got the basic code from ChatGPT, but it was buggy and lacked genericity (new word, maybe it will catch on). So with a bit of Googling and a little common sense, I adapted the code to suit my needs and maybe yours.

An EventAggregator broker reference needs to be placed in a global area that is accessible to all that are needing to use the EventAggregator framework. In my C# WinForms application, I placed the broker in Program.cs.

C#
public static EventAggregator<IEventArgs<Object>> g_aggregator = 
    new EventAggregator<IEventArgs<Object>>();    

The heart of this EventAggregator implementation is the EventAggregator class. It provides the Publish and Subscribe methods that take a generic event type, based on the IEventArgs interface and stores the Event type and a list of delegates in a generic Dictionary data structure.

The Subscribe method first extracts the eventType from the Action TEvent then checks whether the eventType has an entry in the Dictionary; if it does not, then a new entry is created and if it does already contain an entry, the delegate is added to the List of delegates.

In the Publish method; the eventType is extracted and if there is an entry in the Dictionary, then the delegates in the delegate list are invoked. If there are no entries, nothing is done and the method just returns to the caller.

C#
public class EventAggregator<T>
{
private readonly Dictionary<Type, List<Delegate>> subscribers = 
                            new Dictionary<Type, List<Delegate>>();

// Subscribe method to register an event handler
public void Subscribe<TEvent>(Action<TEvent> handler)
{
    Type eventType = typeof(TEvent);

    if (!subscribers.TryGetValue(eventType, out var handlers))
    {
        handlers = new List<Delegate*gt;();
        subscribers[eventType] = handlers;
    }

    handlers.Add(handler);
}

// Publish method to raise an event and notify subscribers
public void Publish<TEvent>(TEvent message)
{
    Type eventType = typeof(TEvent);

    if (subscribers.TryGetValue(eventType, out var handlers))
    {
        foreach (Action<TEvent> handler in handlers)
        {
            handler.Invoke(message);
        }
    }
}   

I chose a very generic test case for evaluating the usefulness of the EventAggregator. It utilizes a TestMessage based on the IEventArgs interface and includes a reference to the Test class.

C#
public interface IEventArgs<T>
{
    T GetData();
}

public class TestMessage : IEventArgs<Test>
{
    Test test { get; }

    public TestMessage(string s, int i)
    {
        test = new Test(i, s);
    }

    public Test GetData()
    {
        return test;
    }
}

public class Test
{
    public int IntProp { get; set; }
    public string StrProp { get; set; }

    public Test(int i, string s)
    {
        IntProp = i;
        StrProp = s;
    }

    public override string ToString()
    {
        return StrProp + " - " + IntProp.ToString();
    }
}  

To Subscribe to the TestMessage type message, you need only to call the Subscribe method and provide the type of message you want to receive and a handler to process the message.

C#
Program.g_aggregator.Subscribe<TestMessage>(HandleTestMessage);

private void HandleTestMessage(TestMessage message)
{
    MessageBox.Show($"Received message: {message.GetData().ToString()}");
}   

To Publish a message is just as simple, just provide a message of the type you wish to send and post it to the EventAggregator's Publish method.

C#
Program.g_aggregator.Publish(new TestMessage("TestMessage - ", 42));

Although the implementation of the EventAggregator is a very simple example of a messaging framework, it has a lot of flexibility. I chose this implementation over other frameworks of this kind because this implementation is a lot simpler and has less of a footprint.

History

  • 21st January, 2024: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
United States United States
Currently enjoying retirement and working on projects without pressure, deadlines or any kind of management.

Comments and Discussions

 
QuestionNice one Pin
Terry Hutt23-Jan-24 7:11
Terry Hutt23-Jan-24 7:11 
AnswerRe: Nice one Pin
Mike Hankey23-Jan-24 7:25
mveMike Hankey23-Jan-24 7:25 
QuestionFeedback Pin
Darrell Tunnell22-Jan-24 14:15
Darrell Tunnell22-Jan-24 14:15 
AnswerRe: Feedback Pin
Mike Hankey23-Jan-24 0:54
mveMike Hankey23-Jan-24 0:54 
WeakReference Class (System) | Microsoft Learn[^]
Quote:
Represents a weak reference, which references an object while still allowing that object to be reclaimed by garbage collection.


It allows the object to be eligible when there no references to it, good when there are a lot of messages. I could have used Object, in fact I have changed the code to reflect in the article and the download.

Thanks for the feedback.
"Ten men in the country could buy the world and ten million can’t buy enough to eat." Will Rogers
PartsBin an Electronics Part Organizer - Release Version 1.3.0 JaxCoder.com
Latest Article: SimpleWizardUpdate


modified 23-Jan-24 7:13am.

GeneralMy vote of 5 Pin
0x01AA21-Jan-24 4:49
mve0x01AA21-Jan-24 4:49 
GeneralRe: My vote of 5 Pin
Mike Hankey21-Jan-24 8:13
mveMike Hankey21-Jan-24 8:13 
GeneralRe: My vote of 5 Pin
Niemand2523-Jan-24 0:42
professionalNiemand2523-Jan-24 0:42 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA21-Jan-24 4:18
professionalȘtefan-Mihai MOGA21-Jan-24 4:18 
GeneralRe: My vote of 5 Pin
Mike Hankey21-Jan-24 4:24
mveMike Hankey21-Jan-24 4:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.