public void WeakDelegateWorksWithStaticMethodDelegates() { var action = new DelegateReference( (Action)SomeClassHandler.StaticMethod, false); Assert.IsNotNull(action.Target); }
public virtual SubscriptionToken Subscribe(Action action, ThreadOption threadOption, bool keepSubscriberReferenceAlive) { var actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); ISubscription subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new Subscription(actionReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundDispatcherSubscription(actionReference); break; case ThreadOption.UIThread: if (m_context == null) { throw new InvalidOperationException("To use the UIThread option for subscribing, the EventAggregator must be constructed on the UI thread."); } subscription = new ContextDispatcherSubscription(actionReference, m_context); break; default: subscription = new Subscription(actionReference); break; } return(Subscribe(subscription)); }
/// <summary> /// Subscribe to a specific event. /// <param name="eventName">Name of the event to subscribe to</param> /// <param name="elementId">ElementId of the model element, which specifies when to notify the observer.</param> /// <param name="action">Action to call on notification.</param> /// </summary> public void Subscribe(string eventName, Guid elementId, Action <T> action) { if (String.IsNullOrEmpty(eventName)) { throw new ArgumentException("eventName"); } IDelegateReference actionReference = new DelegateReference(action, false); IDelegateReference filterReference = new DelegateReference(new Predicate <T>(delegate { return(true); }), true); IEventSubscription subscription = new EventSubscription <T>(actionReference, filterReference); lock (dictionary) { if (!dictionary.Keys.Contains(eventName)) { dictionary.Add(eventName, new Dictionary <Guid, List <IEventSubscription> >()); } if (!dictionary[eventName].Keys.Contains(elementId)) { dictionary[eventName].Add(elementId, new List <IEventSubscription>()); } dictionary[eventName][elementId].Add(subscription); } }
/// <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 <see cref="PubSubEvent"/> keeps a reference to the subscriber so it does not get garbage collected.</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="PubSubEvent"/> will maintain a <see 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 unexpected behavior. /// <para/> /// The PubSubEvent collection is thread-safe. /// </remarks> public virtual SubscriptionToken Subscribe(Action action, ThreadOption threadOption, bool keepSubscriberReferenceAlive) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); EventSubscription subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription(actionReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription(actionReference); break; case ThreadOption.UIThread: if (SynchronizationContext == null) { throw new InvalidOperationException(Resources.EventAggregatorNotConstructedOnUIThread); } subscription = new DispatcherEventSubscription(actionReference, SynchronizationContext); break; default: subscription = new EventSubscription(actionReference); break; } return(InternalSubscribe(subscription)); }
/// <summary> /// Subscribe to the event. The observer will be notified, whenever a model element of /// the given domain class type (which does include all descendants) is included in the /// specific event. /// </summary> /// <param name="domainClassInfo">DomainClassInfo specifying when to notify the observer.</param> /// <param name="action">Action to call on the observer.</param> public void Subscribe(DomainClassInfo domainClassInfo, Action <T> action) { IDelegateReference actionReference = new DelegateReference(action, false); IDelegateReference filterReference = new DelegateReference(new Predicate <T>(delegate { return(true); }), true); IEventSubscription subscription = new EventSubscription <T>(actionReference, filterReference); lock (dictionary) { Guid domainClassId = domainClassInfo.Id; if (!dictionary.Keys.Contains(domainClassId)) { dictionary.Add(domainClassId, new List <IEventSubscription>()); } dictionary[domainClassId].Add(subscription); // process descendants foreach (DomainClassInfo info in domainClassInfo.AllDescendants) { domainClassId = info.Id; if (!dictionary.Keys.Contains(domainClassId)) { dictionary.Add(domainClassId, new List <IEventSubscription>()); } dictionary[domainClassId].Add(subscription); } } }
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) { var del = (Delegate)obj; info.SetType(typeof(DelegateReference)); info.AddValue("Delegates", DelegateReference.FlattenDelegate(del)); }
public void NullDelegateThrows() { Assert.ThrowsException <ArgumentNullException>(() => { var action = new DelegateReference(null, true); }); }
/// <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="CompositeWpfEvent{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="CompositeWpfEvent{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 CompositeWpfEvent 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 = new DelegateReference(filter, keepSubscriberReferenceAlive); 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; default: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; } return(base.InternalSubscribe(subscription)); }
/// <summary> /// Subscribes the specified action. /// </summary> /// <param name="action">The action.</param> /// <param name="threadOption">The thread option.</param> /// <param name="keepSubscriberReferenceAlive">if set to <c>true</c> [keep subscriber reference alive].</param> /// <param name="filter">The filter.</param> /// <returns></returns> public override SubscriptionToken Subscribe(Action <TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate <TPayload> filter) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); IDelegateReference filterReference = filter != null ? new DelegateReference(filter, keepSubscriberReferenceAlive) : new DelegateReference(EmptyPredicate, true); EventSubscription <TPayload> subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new CiEventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.BackgroundThread: subscription = new CiBackgroundEventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.UIThread: subscription = new CiDispatcherEventSubscription <TPayload>(actionReference, filterReference, SynchronizationContext); break; default: subscription = new CiEventSubscription <TPayload>(actionReference, filterReference); break; } return(InternalSubscribe(subscription)); }
/// <summary> /// Subscribes the given delegate reference to the SelectionChanging event. The delegate will be invoked on the specified thread. /// </summary> /// <param name="actionReference"></param> /// <param name="threadOption"></param> /// <returns></returns> public SubscriptionToken Subscribe(IDelegateReference actionReference, ThreadOption threadOption) { IDelegateReference filterReference = new DelegateReference(new Predicate <SelectionBase <T> >(_ => true), true); EventSubscription <SelectionBase <T> > subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription <SelectionBase <T> >(actionReference, filterReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription <SelectionBase <T> >(actionReference, filterReference); break; case ThreadOption.UIThread: subscription = new DispatcherEventSubscription <SelectionBase <T> >(actionReference, filterReference, UIDispatcher); break; default: throw new NotImplementedException("Thread Option not available."); // Impossible to happen } return(base.InternalSubscribe(subscription)); }
/// <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="CompositeSynchronizationContextEvent{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="CompositeSynchronizationContextEvent{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 CompositeSynchronizationContextEvent 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 = new DelegateReference(filter, keepSubscriberReferenceAlive); 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.SubscriberAffinityThread: subscription = new CompositeEventSubscription <TPayload>(actionReference, filterReference, SynchronizationContext.Current); break; default: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; } return(base.InternalSubscribe(subscription)); }
/// <summary> /// Subscribes a delegate to an event. /// </summary> /// <param name="action">The delegate that gets executed when the event is published.</param> /// <param name="keepSubscriberReferenceAlive">When <see langword="true"/>, the <see cref="PubSubEvent"/> keeps a reference to the subscriber so it does not get garbage collected.</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="PubSubEvent"/> will maintain a <see 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 unexpected behavior. /// <para/> /// The PubSubEvent collection is thread-safe. /// </remarks> public virtual SubscriptionToken Subscribe(Action action, bool keepSubscriberReferenceAlive = true) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); EventSubscription subscription = new EventSubscription(actionReference); return(InternalSubscribe(subscription)); }
public void Construct_WeakReferenceStaticDelegate_ShouldSet() { // Prepare var delegateReference = new DelegateReference((Action)ClassFixture.StaticEmptyMethod, false); // Assert Assert.NotNull(delegateReference.Delegate); }
public void TargetEqualsActionShouldReturnTrue() { var classHandler = new SomeClassHandler(); Action <string> myAction = new Action <string>(classHandler.MyAction); var weakAction = new DelegateReference(myAction, false); Assert.True(weakAction.TargetEquals(new Action <string>(classHandler.MyAction))); }
public void KeepAlivePreventsDelegateFromBeingCollected() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action <string>)delegates.DoEvent, true); delegates = null; GC.Collect(); Assert.NotNull(delegateReference.Target); }
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() { string something = null; Action <string> myAction = (arg => something = arg); var weakAction = new DelegateReference(myAction, false); ((Action <string>)weakAction.Target)("payload"); Assert.AreEqual("payload", something); }
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 NotKeepAliveAllowsDelegateToBeCollected() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action <string>)delegates.DoEvent, false); delegates = null; GC.Collect(); Assert.Null(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.Equal("payload", classHandler.MyActionArg); }
public void TargetEqualsNullShouldReturnFalseIfTargetAlive() { SomeClassHandler handler = new SomeClassHandler(); var weakHandlerRef = new WeakReference(handler); var action = new DelegateReference((Action <string>)handler.DoEvent, false); Assert.False(action.TargetEquals(null)); Assert.True(weakHandlerRef.IsAlive); GC.KeepAlive(handler); }
public void Not_Keep_Alive_Should_Allow_Delegate_To_Be_Collected() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action <string>)delegates.DoEvent, false); // ReSharper disable RedundantAssignment delegates = null; // ReSharper restore RedundantAssignment GC.Collect(); Assert.Null(delegateReference.Target); }
public void Keep_Alive_Should_Prevent_Delegate_From_Being_Collected() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action <string>)delegates.DoEvent, true); // ReSharper disable RedundantAssignment delegates = null; // ReSharper restore RedundantAssignment GC.Collect(); Assert.NotNull(delegateReference.Target); }
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.False(weakHandlerRef.IsAlive); Assert.Null(action.Target); }
public void NotKeepAliveKeepsDelegateIfStillAlive() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action <string>)delegates.DoEvent, false); GC.Collect(); Assert.IsNotNull(delegateReference.Target); delegates = null; GC.Collect(); Assert.IsNull(delegateReference.Target); }
public void TargetShouldReturnAction() { //string something = null; //Action<string> myAction = (arg => something = arg); SomeClassHandler 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", something); Assert.AreEqual("payload", classHandler.Value); }
public void Should_Return_Null_If_Target_NotAlive() { SomeClassHandler handler = new SomeClassHandler(); var weakHandlerRef = new WeakReference(handler); var action = new DelegateReference((Action <string>)handler.DoEvent, false); // ReSharper disable RedundantAssignment handler = null; // ReSharper restore RedundantAssignment GC.Collect(); Assert.False(weakHandlerRef.IsAlive); Assert.Null(action.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 async Task GetDelegate_DelegateNotAlive_ShouldReturnNull() { // Prepare var classFixture = new ClassFixture(); var delegateReference = new DelegateReference((Action)classFixture.EmptyMethod, false); // Act classFixture = null !; await Task.Delay(100); GC.Collect(); // Assert Assert.Null(delegateReference.Delegate); }
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); }
public async Task Construct_KeepReferenceAliveFalse_ShouldGetGarbageCollected() { // Prepare Action referenceAction = () => { }; var delegateReference = new DelegateReference(referenceAction, false); // Act referenceAction = null !; await Task.Delay(100); GC.Collect(); // Assert Assert.NotNull(delegateReference.Delegate); }
public void NotKeepAliveKeepsDelegateIfStillAlive() { var delegates = new SomeClassHandler(); var delegateReference = new DelegateReference((Action <string>)delegates.DoEvent, false); GC.Collect(); Assert.NotNull(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.Null(delegateReference.Target); }
public void ShouldAllowCollectionOfOriginalDelegate() { string something = null; Action <string> myAction = (arg => something = arg); 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", something); }
public void NullDelegateThrows() { Assert.ThrowsException<ArgumentNullException>(() => { var action = new DelegateReference(null, true); }); }
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 WeakDelegateWorksWithStaticMethodDelegates() { var action = new DelegateReference((Action)SomeClassHandler.StaticMethod, false); Assert.IsNotNull(action.Target); }
public void NullDelegateThrows() { var action = new DelegateReference(null, true); }