Publisher/Subscriber

时间:2022-05-27 20:26:38
 public interface IPublisher
{
void Publish<T>(T data); void Subscribe<T>(object subscriber, Action<T> pHandler); void Unsubscribe(object subscriber); void Unsubscribe<T>(object subscriber, Action<T> pHandler);
}
public class Publisher : IPublisher
{
public Publisher()
{
} internal List<Handler> _handlers = new List<Handler>(); internal object _locker = new object(); public void Publish<T>(T data = default(T))
{
List<Handler> handlerList; lock (_locker)
{
handlerList = new List<Handler>(_handlers.Count); var handlersToRemove = new List<Handler>(_handlers.Count); foreach (var handler in _handlers)
{
if (!handler.Sender.IsAlive)
{
handlersToRemove.Add(handler);
}
else if (handler.Type.GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()))
{
handlerList.Add(handler);
}
} foreach (var htr in handlersToRemove)
{
_handlers.Remove(htr);
}
} foreach (var hl in handlerList)
{
((Action<T>)hl.Action)(data);
}
} public void Subscribe<T>(Action<T> pHandler)
{
Subscribe(this, pHandler);
} public void Subscribe<T>(object subscriber, Action<T> pHandler)
{
var item = new Handler
{
Action = pHandler,
Sender = new WeakReference(subscriber),
Type = typeof(T)
}; lock (_locker)
{
_handlers.Add(item);
}
} public void Unsubscribe()
{
Unsubscribe(this);
} public void Unsubscribe(object subscriber)
{
lock (_locker)
{
var query = _handlers.Where(a => !a.Sender.IsAlive ||
a.Sender.Target.Equals(subscriber)); foreach (var h in query.ToList())
{
_handlers.Remove(h);
}
}
} public void Unsubscribe<T>()
{
Unsubscribe<T>(this);
} public void Unsubscribe<T>(Action<T> pHandler)
{
Unsubscribe(this, pHandler);
} public void Unsubscribe<T>(object subscriber, Action<T> pHandler = null)
{
lock (_locker)
{
var query = _handlers.Where(a => !a.Sender.IsAlive ||
a.Sender.Target.Equals(subscriber) && a.Type == typeof(T)); if (pHandler != null)
{
query = query.Where(a => a.Action.Equals(pHandler));
} foreach (var h in query.ToList())
{
_handlers.Remove(h);
}
}
} internal class Handler
{
public Delegate Action { get; set; }
public WeakReference Sender { get; set; }
public Type Type { get; set; }
}
}