using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; namespace EventBus { public sealed class EventBroker : IEventBroker,IDisposable { private static readonly Lazy _eventBroker = new Lazy(() => new EventBroker()); private EventBroker() { } string GetHash() { return DateTime.Now.ToLongTimeString(); } public static EventBroker Instance => _eventBroker.Value; private readonly Dictionary> _list = new Dictionary>(); private bool disposedValue; public IEventData GetEvent() { lock (_list) { if (_list.TryGetValue(typeof(EventData), out List? baseevent)) { baseevent ??= new List(); if (baseevent.Count == 0) baseevent.Add(new EventData(GetHash())); return (IEventData)baseevent.First(); } else { EventData eventData = new EventData(GetHash()); _list.Add(typeof(EventData), new List() { eventData }); return eventData; } } } public IAnonymousEventData GetEvent(string eventName) { lock (_list) { ArgumentNullException.ThrowIfNullOrEmpty(eventName); if (_list.TryGetValue(typeof(IAnonymousEventData), out List? baseevent)) { baseevent ??= new List(); if (!baseevent.Where(x => x is AnonymousEventData && x.EventName.Contains(eventName)).Any()) baseevent.Add(new AnonymousEventData(eventName, GetHash())); return (IAnonymousEventData)baseevent.Where(x => x is AnonymousEventData && (x as AnonymousEventData)!.EventName.Contains(eventName)).First(); } else { AnonymousEventData eventData = new AnonymousEventData(eventName, GetHash()); _list.Add(typeof(IAnonymousEventData), new List() { eventData }); return eventData; } } } public IAnonymousEventData GetEvent(string eventName) { lock (_list) { ArgumentNullException.ThrowIfNullOrEmpty(eventName); if (_list.TryGetValue(typeof(IAnonymousEventData), out List? baseevent)) { baseevent ??= new List(); if (!baseevent.Where(x => x is AnonymousEventData && x.EventName.Contains(eventName)).Any()) baseevent.Add(new AnonymousEventData(eventName, GetHash())); return (IAnonymousEventData)baseevent.Where(x => x is AnonymousEventData && (x as AnonymousEventData)!.EventName.Contains(eventName)).First(); } else { AnonymousEventData eventData = new AnonymousEventData(eventName, GetHash()); _list.Add(typeof(IAnonymousEventData), [eventData]); return eventData; } } } public IEventData GetEvent() { lock (_list) { if (_list.TryGetValue(typeof(EventData), out List? baseevent)) { baseevent ??= new List(); if (baseevent.Count == 0) baseevent.Add(new EventData(GetHash())); return (IEventData)baseevent.First(); } else { EventData eventData = new EventData(GetHash()); _list.Add(typeof(EventData), new List() { eventData }); return eventData; } } } internal abstract class BaseValue { public BaseValue(Properties? properties = null) { this.Properties = properties ?? Properties.Default; this.IntPtr = Guid.NewGuid(); } public DateTime DateTime => DateTime.Now; private Properties properties = Properties.Default; public Properties Properties { get => properties ?? Properties.Default; private set => properties = value; } public abstract bool HasDelegate { get; } public Guid IntPtr { get; internal set; } } internal class ActionValue :BaseValue { public ActionValue(Action> action, Properties? properties = null):base(properties) { this.Action = action; } internal Action> Action { get; set; } public override bool HasDelegate => Action != null; public bool Invoke(object sender,TData args,IBaseEventData eventData) { if (Action == null) return false; var eventargs = new EventArgs(args, Instance, IntPtr, eventData); Action.Invoke(sender, eventargs); return eventargs.Handle; } } internal abstract class BaseFuncValue:BaseValue { public BaseFuncValue(Properties? properties = null):base(properties) { } public abstract TResult Invoke(object sender, TData data, IBaseEventData eventData); public abstract List InvokeList(object sender, TData data, IBaseEventData eventData); public abstract bool IsListFunc { get; } } internal class FuncValue : BaseFuncValue { public FuncValue(Func, TRestlt> func, Properties? properties = null):base(properties) { Func = func; } internal Func, TRestlt> Func { get; private set; } public override bool IsListFunc => false; public override bool HasDelegate => Func!=null; public override TRestlt Invoke(object sender, TData data, IBaseEventData eventData) { ArgumentNullException.ThrowIfNull(Func); return Func.Invoke(sender, new EventArgs(data, Instance, IntPtr, eventData, typeof(TRestlt))); } public override List InvokeList(object sender, TData data, IBaseEventData eventData) { throw new NotImplementedException(); } } internal class ListFuncValue : BaseFuncValue { public ListFuncValue(Func, List> func, Properties? properties = null) : base( properties) { Func = func; } public Func, List> Func { get; private set; } public override bool IsListFunc => true; public override bool HasDelegate => Func != null; public override TRestlt Invoke(object sender, TData data, IBaseEventData eventData) { throw new NotImplementedException(); } public override List InvokeList(object sender, TData data, IBaseEventData eventData) { ArgumentNullException.ThrowIfNull(Func); return Func.Invoke(sender, new EventArgs(data, Instance, IntPtr, eventData, typeof(TRestlt))); } } public sealed class EventData : IEventData { public string EventName { get; } public string Hash { get; } internal EventData(string eventName,string hash) { EventName = eventName; Hash = hash; } internal EventData(string hash) : this(hash, hash) { } ConcurrentDictionary> _list = new ConcurrentDictionary>(); public void Publish(object sender, TData data, Properties? properties = null) { try { ArgumentNullException.ThrowIfNull(data); properties ??= Properties.Default; if (_list.IsEmpty) return; var templist = _list.Where(x => x.Value.Properties.FilterRule(properties) && x.Value.HasDelegate).Select(x => x.Value).ToList(); if (templist.Count == 0) return; foreach (var val in templist) { if (val.Invoke(sender, data, this)) return; } } catch { } } public void UnSubscrip(Guid guid) { lock (_list) { if (guid == Guid.Empty) return; _list.TryRemove(guid,out _); } } public Guid Subscrip(Action> action, Properties? properties = null) { lock (_list) { ArgumentNullException.ThrowIfNull(action); properties ??= Properties.Default; var temp = new ActionValue(action, properties); _list[temp.IntPtr] = temp; return temp.IntPtr; } } public void Clear() { lock (_list) { _list.Clear(); } } public async Task PublishAsync(object sender, TData data, Properties? properties = null) { try { ArgumentNullException.ThrowIfNull(data); properties ??= Properties.Default; if (_list.IsEmpty) return; var temp = _list.Where(x => x.Value.Properties.FilterRule(properties) && x.Value.HasDelegate).Select(x => x.Value).ToList(); if (temp.Count == 0) return; foreach (var val in temp) { if (await Task.Run(() => val.Invoke(sender, data, this))) return; } } catch { } } } public sealed class EventData : IEventData { public string EventName { get; } public string Hash { get; } private readonly ConcurrentDictionary> _list = new ConcurrentDictionary>(); internal EventData(string eventName, string hash) { EventName = eventName; Hash = hash; } internal EventData(string hash) : this(hash, hash) { } public T Publish(object sender, TData data, Properties? properties = null) { ArgumentNullException.ThrowIfNull(data); if (_list.IsEmpty) return Activator.CreateInstance(); properties ??= Properties.Default; var func = _list.Where(x=>x.Value is FuncValue && x.Value.HasDelegate).Where(x => x.Value.Properties.FilterRule(properties)).Select(x=>x.Value).ToList(); if (func.Count == 0) return Activator.CreateInstance(); return func.First().Invoke(sender, data, this); } public List PublishList(object sender, TData data, Properties? properties = null) { ArgumentNullException.ThrowIfNull(data); if (_list.IsEmpty) return new List(); properties ??= Properties.Default; var func = _list.Where(x => x.Value is ListFuncValue && x.Value.HasDelegate).Where(x => x.Value.Properties.FilterRule(properties)).Select(x => x.Value).ToList(); if (func.Count == 0) return new List(); return func.First().InvokeList(sender, data, this); } public Guid Subscrip(Func, T> func, Properties? properties = null) { ArgumentNullException.ThrowIfNull(func); properties ??= Properties.Default; var temp = new FuncValue(func, properties); _list[temp.IntPtr] = temp; return temp.IntPtr; } public Guid SubscripList( Func, List> func, Properties? properties = null) { ArgumentNullException.ThrowIfNull(func); properties ??= Properties.Default; var temp = new ListFuncValue(func, properties); _list[temp.IntPtr] = temp; return temp.IntPtr; } public void UnSubscrip(Guid intPtr) { if (intPtr == Guid.Empty) return; _list.TryRemove(intPtr,out var _); } public void Clear() { _list.Clear(); } public async Task PublishAsync(object sender, TData data, Properties? properties = null) { ArgumentNullException.ThrowIfNull(data); if (_list.IsEmpty) return Activator.CreateInstance(); properties ??= Properties.Default; var func = _list.Where(x => x.Value is FuncValue && x.Value.HasDelegate).Where(x => x.Value.Properties.FilterRule(properties)).Select(x => x.Value).ToList(); if (func.Count == 0) return Activator.CreateInstance(); return await Task.Run(()=> func.First().Invoke(sender, data, this)); } public async Task> PublishListAsync(object sender, TData data, Properties? properties = null) { ArgumentNullException.ThrowIfNull(data); if (_list.IsEmpty) return new List(); properties ??= Properties.Default; var func = _list.Where(x => x.Value is ListFuncValue && x.Value.HasDelegate).Where(x => x.Value.Properties.FilterRule(properties)).Select(x => x.Value).ToList(); if (func.Count == 0) return new List(); return await Task.Run(() => func.First().InvokeList(sender, data, this)); } } public sealed class AnonymousEventData : IAnonymousEventData { public string EventName { get; } public string Hash { get; } internal AnonymousEventData(string eventName, string hash) { EventName = eventName; Hash = hash; } internal AnonymousEventData(string hash) : this(hash, hash) { } ConcurrentDictionary> _list = new ConcurrentDictionary>(); public void Publish(object sender, Properties? properties, params object[] data) { properties ??= Properties.Default; if (_list.IsEmpty) return; var templist = _list.Where(x => x.Value.Properties.FilterRule(properties) && x.Value.HasDelegate).ToList(); if (templist.Count == 0) return; foreach (var val in templist) { var args = new EventArgs(data, Instance, val.Value.IntPtr,this); val.Value.Action.Invoke(sender, args); if (args.Handle) return; } } public void UnSubscrip(Guid guid) { if (guid == Guid.Empty) return; _list.TryRemove(guid, out _); } public Guid Subscrip(Action> action, Properties? properties=null) { ArgumentNullException.ThrowIfNull(action); properties ??= Properties.Default; var act = new ActionValue(action, properties); _list[act.IntPtr] = act; return act.IntPtr; } public void Clear() => _list.Clear(); public async Task PublishAsync(object sender, Properties? properties = null, params object[] data) { properties ??= Properties.Default; if (_list.IsEmpty) return; var templist = _list.Where(x => x.Value.Properties.FilterRule(properties) && x.Value.HasDelegate).Select(x => x.Value).ToList(); foreach (var val in templist) { var args = new EventArgs(data, Instance, val.IntPtr, this); await System.Threading.Tasks.Task.Run(() => val.Action.Invoke(sender, args)); if (args.Handle) return; } } } public sealed class AnonymousEventData : IAnonymousEventData { public string EventName { get; } public string Hash { get; } ConcurrentDictionary> _list = new ConcurrentDictionary>(); internal AnonymousEventData(string eventName, string hash) { EventName = eventName; Hash = hash; } internal AnonymousEventData(string hash) : this(hash, hash) { } public T Publish(object sender, Properties? properties, params object[] data) { if (_list.IsEmpty) return Activator.CreateInstance(); properties ??= Properties.Default; var func = _list.Where(x => x.Value is FuncValue && x.Value.HasDelegate).Where(x => x.Value.Properties.FilterRule(properties)).Select(x=>x.Value).ToList(); if (func.Count == 0) return Activator.CreateInstance(); return func.First().Invoke(sender, data, this); } public List PublishList(object sender, Properties? properties, params object[] data) { if (_list.IsEmpty) return new List(); properties ??= Properties.Default; var func = _list.Where(x => x.Value is ListFuncValue && x.Value.HasDelegate).Where(x => x.Value.Properties.FilterRule(properties)).Select(x => x.Value).ToList(); if (func.Count == 0) return new List(); return func.First().InvokeList(sender, data, this); } public Guid Subscrip(Func, T> func, Properties? properties=null) { ArgumentNullException.ThrowIfNull(func); properties ??= Properties.Default; var tempfunc = new FuncValue(func, properties); _list[tempfunc.IntPtr] = tempfunc; return tempfunc.IntPtr; } public Guid SubscripList(Func, List> func, Properties? properties=null) { ArgumentNullException.ThrowIfNull(func); properties ??= Properties.Default; var tempfunc = new ListFuncValue(func, properties); _list[tempfunc.IntPtr] = tempfunc; return tempfunc.IntPtr; } public void UnSubscrip(Guid guid) { if (guid == Guid.Empty) return; _list.TryRemove(guid, out _); } public void Clear() { _list.Clear(); } public async Task PublishAsync(object sender, Properties? properties = null, params object[] data) { if (_list.IsEmpty) return Activator.CreateInstance(); properties ??= Properties.Default; var func = _list.Where(x => x.Value is FuncValue && x.Value.HasDelegate).Where(x => x.Value.Properties.FilterRule(properties)).Select(x=>x.Value).ToList(); if (func.Count == 0) return Activator.CreateInstance(); return await Task.Run(()=> func.First().Invoke(sender, data, this)); } public async Task> PublishListAsync(object sender, Properties? properties = null, params object[] data) { if (_list.IsEmpty) return new List(); properties ??= Properties.Default; var func = _list.Where(x => x.Value is ListFuncValue && x.Value.HasDelegate).Where(x => x.Value.Properties.FilterRule(properties)).Select(x => x.Value).ToList(); if (func.Count == 0) return new List(); return await Task.Run(()=> func.First().InvokeList(sender, data, this)); } } private void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { _list.Values.ToList().ForEach(x => x?.ToList().ForEach(y=>y.Clear())); _list.Clear(); } // TODO: 释放未托管的资源(未托管的对象)并替代终结器 // TODO: 将大型字段设置为 null disposedValue = true; } } // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器 // ~EventBroker() // { // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中 // Dispose(disposing: false); // } public void Dispose() { // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中 Dispose(disposing: true); GC.SuppressFinalize(this); } } }