事件总线 EventHub
一个 C# 的全局事件总线,用来分发事件,比如可以在 Blazor 里,从服务触发 UI 的弹窗事件
/// <summary> /// 事件总线 /// </summary> public static class EventHub { static ConcurrentDictionary<EventType, Delegate> _hubs = new ConcurrentDictionary<EventType, Delegate>(); /// <summary> /// 添加监听事件 /// </summary> /// <param name="eventType"></param> /// <param name="delegate"></param> public static void on(EventType @eventType, Delegate @delegate) { _hubs.AddOrUpdate(@eventType, @delegate, (k, v) => Delegate.Combine(v, @delegate)); } /// <summary> /// 移除监听事件 /// </summary> /// <param name="eventType"></param> /// <param name="delegate"></param> public static void off(EventType @eventType, Delegate @delegate) { // 把 Delegate 下,和 @delegate 相同指针的方法全删掉 nint ptr = @delegate.Method.MethodHandle.GetFunctionPointer(); _hubs.TryRemove(@eventType, out Delegate? outDelegates); if (outDelegates is not null) { List<Delegate> list = outDelegates.GetInvocationList().ToList(); var allLst = list.FindAll(item => item.Method.MethodHandle.GetFunctionPointer() != ptr); foreach (var d in allLst) { on(@eventType, d); } } } public static void emit(EventType @eventType) { Delegate[]? delegates = getMethods(@eventType); if (delegates is null) return; foreach (var d in delegates) { if (d.Target is null) continue; (d as Action)?.Invoke(); } } public static void emit<T>(EventType @eventType, T arg1) { Delegate[]? delegates = getMethods(@eventType); if (delegates is null) return; foreach (var d in delegates) { if (d.Target is null) continue; (d as Action<T>)?.Invoke(arg1); } } public static void emit<T1, T2>(EventType @eventType, T1 arg1, T2 arg2) { Delegate[]? delegates = getMethods(@eventType); if (delegates is null) return; foreach (var d in delegates) { if (d.Target is null) continue; (d as Action<T1, T2>)?.Invoke(arg1, arg2); } } public static void emit<T1, T2, T3>(EventType @eventType, T1 arg1, T2 arg2, T3 arg3) { Delegate[]? delegates = getMethods(@eventType); if (delegates is null) return; foreach (var d in delegates) { if (d.Target is null) continue; (d as Action<T1, T2, T3>)?.Invoke(arg1, arg2, arg3); } } public static void emit<T1, T2, T3, T4>(EventType @eventType, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { Delegate[]? delegates = getMethods(@eventType); if (delegates is null) return; foreach (var d in delegates) { if (d.Target is null) continue; (d as Action<T1, T2, T3, T4>)?.Invoke(arg1, arg2, arg3, arg4); } } public static void emit<T1, T2, T3, T4, T5>(EventType @eventType, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) { Delegate[]? delegates = getMethods(@eventType); if (delegates is null) return; foreach (var d in delegates) { if (d.Target is null) continue; (d as Action<T1, T2, T3, T4, T5>)?.Invoke(arg1, arg2, arg3, arg4, arg5); } } public static void emit<T1, T2, T3, T4, T5, T6>(EventType @eventType, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) { Delegate[]? delegates = getMethods(@eventType); if (delegates is null) return; foreach (var d in delegates) { if (d.Target is null) continue; (d as Action<T1, T2, T3, T4, T5, T6>)?.Invoke(arg1, arg2, arg3, arg4, arg5, arg6); } } public static void emit<T1, T2, T3, T4, T5, T6, T7>(EventType @eventType, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) { Delegate[]? delegates = getMethods(@eventType); if (delegates is null) return; foreach (var d in delegates) { if (d.Target is null) continue; (d as Action<T1, T2, T3, T4, T5, T6, T7>)?.Invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } } static Delegate[]? getMethods(EventType @eventType) { _hubs.TryGetValue(@eventType, out Delegate? outDelegates); return outDelegates?.GetInvocationList(); } }
public enum EventType { /// <summary> /// 控制台日志 /// </summary> ConsoleLog, /// <summary> /// 展示消息 /// </summary> ShowInfo, /// <summary> /// 展示警告 /// </summary> ShowWarring, /// <summary> /// 展示错误 /// </summary> ShowError, }
使用方法如下:
1,设置监听事件
2,使用调用监听,服务的 emit 可以触发 UI 的弹窗;
当然 EventHub 还可以用在别处