public IDisposable Subscribe <T>(WeakAction <T> action) where T : class, IMessage { NotNull(action, "action"); Type key = typeof(T); var container = CheckForKey(key); _locker.SafeWork(() => { if (container.Contains(action)) { throw new InvalidOperationException("This subscriber has been already subscribed to this event."); } container.Add(action); }); return(new Disposer(() => { HashSet <WeakAction> dump; Type[] args = action.GetType().GetGenericArguments(); if (args != null && args.Length > 0) { if (!_lazyDict.Value.TryGetValue(args[0], out dump)) { return; } _locker.SafeWork(() => dump.Remove(action)); (action).MarkForDeletion(); } })); }
public IDisposable Subscribe <T>(ISubscriber <T> subscriber) where T : class, IMessage { NotNull(subscriber, "subscriber"); Type key = typeof(T); HashSet <WeakReference> container = CheckForKey(key); HashSet <IMessage> delayedMsgs; if (container.Count == 0 && _lazyDefferMsgs.Value.TryGetValue(key, out delayedMsgs) && delayedMsgs != null) { Parallel.ForEach(delayedMsgs, item => { if ((subscriber as INotify <T>) != null) { _locker.SafeWork(() => (subscriber as INotify <T>).Notify(item as T)); } else if ((subscriber as ISubscriber <T>) != null) { _locker.SafeWork(() => (subscriber as ISubscriber <T>).HandleEvent(item as T)); } }); } WeakReference weak = new WeakReference(subscriber); _locker.SafeWork(() => { if (container.Contains(weak)) { throw new InvalidOperationException("This subscriber has been already subscribed to this event."); } container.Add(weak); }); return(new Disposer(() => { HashSet <WeakReference> dump; Type msgType = subscriber.GetType().GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ISubscriber <>)) .Select(x => x.GetGenericArguments()[0]).FirstOrDefault(); if (msgType == null || !_lazyDict.Value.TryGetValue(msgType, out dump)) { return; } _locker.SafeWork(() => dump.Remove(weak)); })); }