using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace OpenSEMI.Core.Publisher { public class Publisher : IPublisher { internal class Handler { public Delegate Action { get; set; } public WeakReference Sender { get; set; } public Type Type { get; set; } } internal List _handlers = new List(); internal object _locker = new object(); public void Publish(T data = default(T)) { List list = default(List); lock (_locker) { list = new List(_handlers.Count); List list2 = new List(_handlers.Count); foreach (Handler handler in _handlers) { if (!handler.Sender.IsAlive) { list2.Add(handler); } else if (handler.Type.GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())) { list.Add(handler); } } foreach (Handler item in list2) { _handlers.Remove(item); } } foreach (Handler item2 in list) { ((Action)item2.Action)(data); } } public void Subscribe(Action pHandler) { Subscribe(this, pHandler); } public void Subscribe(object subscriber, Action pHandler) { Handler handler = new Handler(); handler.Action = pHandler; handler.Sender = new WeakReference(subscriber); handler.Type = typeof(T); Handler item = handler; lock (_locker) { _handlers.Add(item); } } public void Unsubscribe() { Unsubscribe(this); } public void Unsubscribe(object subscriber) { lock (_locker) { IEnumerable source = from a in _handlers where !a.Sender.IsAlive || a.Sender.Target.Equals(subscriber) select a; foreach (Handler item in source.ToList()) { _handlers.Remove(item); } } } public void Unsubscribe() { Unsubscribe((object)this, (Action)null); } public void Unsubscribe(Action pHandler) { Unsubscribe(this, pHandler); } public void Unsubscribe(object subscriber, Action pHandler = null) { lock (_locker) { IEnumerable source = from a in _handlers where !a.Sender.IsAlive || (a.Sender.Target.Equals(subscriber) && a.Type == typeof(T)) select a; if (pHandler != null) { source = from a in source where a.Action.Equals(pHandler) select a; } foreach (Handler item in source.ToList()) { _handlers.Remove(item); } } } } }