Firing Events Anywhere With Event Aggregator

If you create a Windows client application, you’ll often need to fire an event from one window / form to others. We can do it easily by creating an event aggregator, which receives event notifications and process them by their name.

public delegate void CommonHandler(object data);

public sealed class EventAggregator
{
    public static object locker = new object();
    public static EventAggregator instance = null;
    private Dictionary<string, List<CommonHandler>> dicEvent = null;

    private EventAggregator()
    {
        dicEvent = new Dictionary<string, List<CommonHandler>>();
    }

    public static EventAggregator GetInstance()
    {
        if (instance == null)
        {
            lock (locker)
            {
                if (instance == null)
                {
                    instance = new EventAggregator();
                }
            }
        }
        return instance;
    }

    public void Subscribe(string eventName, CommonHandler handler)
    {
        lock (locker)
        {
            if (!dicEvent.ContainsKey(eventName))
                dicEvent[eventName] = new List<CommonHandler>();
            if (!dicEvent[eventName].Contains(handler))
                dicEvent[eventName].Add(handler);
        }
    }

    public void Publish(string eventName, object data)
    {
        lock (locker)
        {
            if (dicEvent.ContainsKey(eventName))
            {
                for (int i = 0; i < dicEvent[eventName].Count; i++)
                {
                    if (dicEvent[eventName][i] != null)
                        dicEvent[eventName][i](data);
                }

            }
        }
    }

    public void Unsubscribe(string eventName, CommonHandler handler)
    {
        lock (locker)
        {
            if (dicEvent.ContainsKey(eventName))
            {
                int index = dicEvent[eventName].IndexOf(handler);
                if (index > -1)
                    dicEvent[eventName].RemoveAt(index);
                if (dicEvent[eventName].Count == 0)
                    dicEvent.Remove(eventName);
            }
        }
    }
}

The implementation above is singleton class, but you may change it into static class if you don’t wish to add other instance class behavior (such as indexer, implements interface, etc).
You may also change the delegate definition to suit your need.