//некое событие public interface IEvent{} //обработчик события public interface IEventHandler where T : class, IEvent { public void HandleEvent(T @event); } public class EventDispatcher{ private Dictionary> _handlers = new(); private object _locker = new(); public void Subscribe(IEventHandler handler) where T : class, IEvent { var type = typeof(T); lock(_locker){ if(!_handlers.TryGetValue(type, out var handlers)){ handlers = new(); _handlers[type] = handlers; } var refs = handlers.Find(x=>x.Target == handler); if(refs is not null){ throw new InvalidOperationException(); } refs = new(handler); handlers.Add(refs); } } public void Unsubscribe(IEventHandler handler) where T : class, IEvent { var type = typeof(T); lock(_locker){ if(!_handlers.ContainsKey(type)){ throw new InvalidOperationException(); } var handlers = _handlers[type]; var refs = handlers.Find(x=>x.Target == handlers); if(refs is null){ throw new InvalidOperationException(); } handlers.Remove(refs); } } public void Handle(T @event) where T : class, IEvent { var type = typeof(T); //не даем подписываться пока идет обработка))) lock(_locker){ if(!_handlers.ContainsKey(type)){ return; } var handlers = _handlers[type]; List toRemove = new(); foreach(var handlerRef in handlers){ if(!handlerRef.IsAlive){ toRemove.Add(handlerRef); continue; } if(handlerRef.Target is null){ toRemove.Add(handlerRef); continue; } var handler = handlerRef.Target as IEventHandler; if(handler is null){ toRemove.Add(handlerRef); continue; } handler.HandleEvent(@event); } foreach(var i in toRemove){ handlers.Remove(i); } } } }