public void NotKeepAliveAllowsDelegateToBeCollected() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action<string>)delegates.DoEvent, false); delegates = null; GC.Collect(); Assert.IsNull(delegateReference.Target); }
public void TargetShouldReturnAction() { var classHandler = new SomeClassHandler(); Action<string> myAction = new Action<string>(classHandler.MyAction); var weakAction = new DelegateReference(myAction, false); ((Action<string>)weakAction.Target)("payload"); Assert.AreEqual("payload", classHandler.MyActionArg); }
public void KeepAlivePreventsDelegateFromBeingCollected() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action<string>)delegates.DoEvent, true); delegates = null; GC.Collect(); Assert.IsNotNull(delegateReference.Target); }
public void ShouldAllowCollectionOfOriginalDelegate() { var classHandler = new SomeClassHandler(); Action<string> myAction = new Action<string>(classHandler.MyAction); var weakAction = new DelegateReference(myAction, false); var originalAction = new WeakReference(myAction); myAction = null; GC.Collect(); Assert.IsFalse(originalAction.IsAlive); ((Action<string>)weakAction.Target)("payload"); Assert.AreEqual("payload", classHandler.MyActionArg); }
public void NotKeepAliveKeepsDelegateIfStillAlive() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action<string>)delegates.DoEvent, false); GC.Collect(); Assert.IsNotNull(delegateReference.Target); GC.KeepAlive(delegates); //Makes delegates ineligible for garbage collection until this point (to prevent oompiler optimizations that may release the referenced object prematurely). delegates = null; GC.Collect(); Assert.IsNull(delegateReference.Target); }
/// <summary> /// Subscribes a delegate to an event. /// </summary> /// <param name="action">The delegate that gets executed when the event is published.</param> /// <param name="threadOption">Specifies on which thread to receive the delegate callback.</param> /// <param name="keepSubscriberReferenceAlive">When <see langword="true"/>, the <seealso cref="CompositePresentationEvent{TPayload}"/> keeps a reference to the subscriber so it does not get garbage collected.</param> /// <param name="filter">Filter to evaluate if the subscriber should receive the event.</param> /// <returns>A <see cref="SubscriptionToken"/> that uniquely identifies the added subscription.</returns> /// <remarks> /// If <paramref name="keepSubscriberReferenceAlive"/> is set to <see langword="false" />, <see cref="CompositePresentationEvent{TPayload}"/> will maintain a <seealso cref="WeakReference"/> to the Target of the supplied <paramref name="action"/> delegate. /// If not using a WeakReference (<paramref name="keepSubscriberReferenceAlive"/> is <see langword="true" />), the user must explicitly call Unsubscribe for the event when disposing the subscriber in order to avoid memory leaks or unexepcted behavior. /// /// The CompositePresentationEvent collection is thread-safe. /// </remarks> public virtual SubscriptionToken Subscribe(Action <TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate <TPayload> filter) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); IDelegateReference filterReference; if (filter != null) { filterReference = new DelegateReference(filter, keepSubscriberReferenceAlive); } else { filterReference = new DelegateReference(new Predicate <TPayload>(delegate { return(true); }), true); } EventSubscription <TPayload> subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.UIThread: subscription = new DispatcherEventSubscription <TPayload>(actionReference, filterReference, UIDispatcher); break; case ThreadOption.WinFormUIThread: subscription = new DispatcherEventSubscription <TPayload>(actionReference, filterReference, WinFormUIDispatcher); break; default: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; } return(base.InternalSubscribe(subscription)); }
public void ShouldReturnNullIfTargetNotAlive() { SomeClassHandler handler = new SomeClassHandler(); var weakHandlerRef = new WeakReference(handler); var action = new DelegateReference((Action<string>)handler.DoEvent, false); handler = null; GC.Collect(); Assert.IsFalse(weakHandlerRef.IsAlive); Assert.IsNull(action.Target); }
public void NullDelegateThrows() { var action = new DelegateReference(null, true); }
public void WeakDelegateWorksWithStaticMethodDelegates() { var action = new DelegateReference((Action)SomeClassHandler.StaticMethod, false); Assert.IsNotNull(action.Target); }