C # event bus summary

tags: c#

The event bus is an implementation of the release-subscription mode, is a centralized event handling mechanism that allows different components to communicate with each other and do not need to be interdependent, achieving a decoupling purpose.

Implement an event bus #
Eventbus maintains a dictionary, publisher, and subscribers get an event instance in the event bus and perform the release, subscription operation, and the event instance is responsible for maintenance, and perform the event handler. The process is as follows:

Define event base class #

Event instances need to register in the event bus, define a base class to facilitate the event bus for management, the code is as follows:

///
/// event base class
///
public abstract class EventBase{ }
Event instances need to be managed, performing registered event handlers, in order to adapt to different event parameters, this type is not allowed to instantiate. code show as below:

///
/// generic event
///
///
public abstract class PubSubEvent : EventBase where T : EventArgs
{
protected static readonly object locker = new object();

protected readonly List<Action<object, T>> subscriptions = new List<Action<object, T>>();

public void Subscribe(Action<object, T> eventHandler)
{
    lock (locker)
    {
        if (!subscriptions.Contains(eventHandler))
        {
            subscriptions.Add(eventHandler);
        }
    }
}

public void Unsubscribe(Action<object, T> eventHandler)
{
    lock (locker)
    {
        if (subscriptions.Contains(eventHandler))
        {
            subscriptions.Remove(eventHandler);
        }
    }
}

public virtual void Publish(object sender, T eventArgs)
{
    lock (locker)
    {
        for (int i = 0; i < subscriptions.Count; i++)
        {
            subscriptions[i](sender, eventArgs);
        }
    }
}

}
Define event parameter class #

The event parameter base class inherits Eventargs, adapting to different parameter types using generic parameters, and does not allow such instantiation. code show as below:

///
/// generic event parameters
///
///
public abstract class PubSubEventArgs : EventArgs
{
public T Value { get; set; }
}
Define Eventbus #

Eventbus only provides the management of event instances, and the implementation of the specific event handler is responsible for the event instance. For easy use, the constructor has the function of automatic registration event, and there may be a bug in multiple assemblies. code show as below:

///
/// Event Bus
///
class EventBus
{
private static EventBus _default;
private static readonly object locker = new object();
private Dictionary<Type, EventBase> eventDic = new Dictionary<Type, EventBase>();

/// <summary>
/// Default event bus instance, it is recommended to use this instance
/// </summary>
public static EventBus Default
{
    get
    {
        if (_default == null)
        {
            lock (locker)
            {
                                 // If the instance of the class does not exist, it is created, otherwise it will return directly.
                if (_default == null)
                {
                    _default = new EventBus();                            
                }
            }
        }
        return _default;
    }
}

/// <summary>
 /// Constructor, automatically load EventBase derived class implementation
/// </summary>
public EventBus() 
{
    Type type = typeof(EventBase);
    Type typePubSub = typeof(PubSubEvent<>);
    Assembly assembly = Assembly.GetAssembly(type);
    List<Type> typeList = assembly.GetTypes()
        .Where(t => t != type && t != typePubSub && type.IsAssignableFrom(t))
        .ToList();
    foreach (var item in typeList)
    {
        EventBase eventBase = (EventBase)assembly.CreateInstance(item.FullName);
        eventDic.Add(item, eventBase);
    }
}

/// <summary>
 /// Get an event instance
/// </summary>
 /// <typeparam name = "tevent"> Event type </ typeParam>
/// <returns></returns>
public TEvent GetEvent<TEvent>() where TEvent : EventBase
{
    return (TEvent)eventDic[typeof(TEvent)];
}

/// <summary>
 /// Add event type
/// </summary>
/// <typeparam name="TEvent"></typeparam>
public void AddEvent<TEvent>() where TEvent : EventBase ,new()
{
    lock (locker) 
    {
        Type type = typeof(TEvent);
        if (!eventDic.ContainsKey(type))
        {
            eventDic.Add(type, new TEvent());                    
        }
    }
}

/// <summary>
 /// Remove event type
/// </summary>
/// <typeparam name="TEvent"></typeparam>
public void RemoveEvent<TEvent>() where TEvent : EventBase, new()
{
    lock (locker)
    {
        Type type = typeof(TEvent);
        if (eventDic.ContainsKey(type))
        {
            eventDic.Remove(type);
        }
    }
}

}
Use an event bus #
Event and event parameters #

You need to define events and event parameters before using the event bus. In use, the publisher, the subscriber must also know the type of event type and event parameter. code show as below:

///
/// generic event realizes -TestaEvent, rewriting the trigger logic
///
public class TestAEvent: PubSubEvent
{
public override void Publish(object sender, TestAEventArgs eventArgs)
{
lock (locker)
{
for (int i = 0; i < subscriptions.Count; i++)
{
var action= subscriptions[i];
Task.Run(() => action(sender, eventArgs));
}
}
}
}
///
/// generic event parameters Realize -TestaEventArgs
///
public class TestAEventArgs : PubSubEventArgs { }

///
/// generic event implementation - TestBevent
///
public class TestBEvent : PubSubEvent { }
///
/// generic event parameters Realize -TestBeventargs
///
public class TestBEventArgs : PubSubEventArgs { }
Note: TestaEvent renovates the logic of the event release, each of which is executed in the task.

Define publisher #

The publisher obtain an event instance through an event bus, publish an event on an instance, the code is as follows:

class Publisher
{
public void PublishTeatAEvent(string value)
{
EventBus.Default.GetEvent().Publish(this, new TestAEventArgs() { Value=value});
}

public void PublishTeatBEvent(int value)
{
    EventBus.Default.GetEvent<TestBEvent>().Publish(this, new TestBEventArgs() { Value = value });
}

}
Define subscriber #
1)
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
The subscriber acquire an event instance through an event bus, and subscribe to the event on the instance, the code is as follows:

class ScbscriberA
{
public string Name { get; set; }

public ScbscriberA(string name)
{
    Name = name;
    EventBus.Default.GetEvent<TestAEvent>().Subscribe(TeatAEventHandler);
}

public void TeatAEventHandler(object sender, TestAEventArgs e)
{
    Console.WriteLine(Name+":"+e.Value);
}

}

class ScbscriberB
{
public string Name { get; set; }

public ScbscriberB(string name)
{
    Name = name;
    EventBus.Default.GetEvent<TestBEvent>().Subscribe(TeatBEventHandler);
}

public void Unsubscribe_TeatBEvent() 
{
    EventBus.Default.GetEvent<TestBEvent>().Unsubscribe(TeatBEventHandler);
}

public void TeatBEventHandler(object sender, TestBEventArgs e)
{
    Console.WriteLine(Name + ":" + e.Value);
}

}
actual use#

code show as below:

class Program
{
static void Main(string[] args)
{
Publisher publisher = new Publisher();
ScbscriberA scbscriberA = new ScbscriberA(“scbscriberA”);
ScbscriberB scbscriberB1 = new ScbscriberB(“scbscriberB1”);
ScbscriberB scbscriberB2 = new ScbscriberB(“scbscriberB2”);
publisher.PublishTeatAEvent(“test”);
publisher.PublishTeatBEvent(123);

    scbscriberB2.Unsubscribe_TeatBEvent();
    publisher.PublishTeatBEvent(12345);

    Console.ReadKey();           
}    

}
operation result:

scbscriberB1:123
scbscriberB2:123
scbscriberA:test
scbscriberB1:12345
Summarize#
This event bus only provides basic functions, implementation publishers and subscribers' decoupling, publishers, and subscribers only depend on events do not depend on each other.
I feel that my understanding of the event bus is still inadequate. Welcome everyone to discuss!

Intelligent Recommendation

Otto-Bus event bus

OTTO is an event bus that is designed to make your application's different parts of the application, while still allowing them to communicate effectively. Outo adds a unique function to the extensive ...

Vue - Event Bus ($ Bus)

Problem Description: When the product is loaded, it is not refreshed because this. Scroll is refreshed in Better-scroll, the picture is not loaded, causing the height of ScrollerHeight not to load the...

Vue Event Bus $ BUS

Registration $ bus main.js Launch event Monitor event...

Vue Event Bus: $ BUS

Vue Event Bus: $ BUS Solved questions: Identity between unrelated components (you can also use VUEX) Instructions: 1. Create an event bus: 2. Trigger events and pass parameters: 3. Listen to event Eve...

More Recommendation

$ Bus Event Bus in Vue

Do not talk nonsense, see directly: 1, inmain.js Middleway$bus Bind tovue Prototype 2, put a method out of the component that needs to pass the information, and needs to activate this method in a cert...

Event bus

First, add dependencies Second, add a layout file active_main.xml Activity_second.xml file Third, the procedure First define an event class MianActivity.java secondActivity.java  ...

event-bus

In vue, communication between components is often necessary, and communication between parent and child components is naturally unnecessary. Communication between all components also has a global stat...

Event bus (event-bus) guide

Overview Case Event Publishing precondition IDL definition Critical configuration Publish task service implementation Event release Event subscription rely As a subscriber Is it both the sender of the...

Vue event bus (Event Bus)

Bus bus Use background In the data display project, the side menu bar has a function of expanding and contracting, which causes the width of the right side to change, but the chart does not adapt to t...

Copyright  DMCA © 2018-2026 - All Rights Reserved - www.programmersought.com  User Notice

Top