public void WeakEventHandlerProxy_RaiseEvent_Performance_Within_500x_Non_Reflection_Action() { var testIterations = 10000; var subscriber = new CustomEventSubscriber <EventArgs>(); var proxy = new WeakEventHandlerProxy <EventArgs>(new EventHandler(subscriber.HandleEvent)); var stopwatch = new Stopwatch(); var proxyInvokeStart = stopwatch.ElapsedTicks; stopwatch.Start(); for (var i = 0; i < testIterations; i++) { proxy.RaiseEvent(null, null); } stopwatch.Stop(); var proxyInvokeTicks = stopwatch.ElapsedTicks - proxyInvokeStart; var actionInvokeStart = stopwatch.ElapsedTicks; stopwatch.Start(); for (var i = 0; i < testIterations; i++) { subscriber.HandleEvent(null, null); } stopwatch.Stop(); var actionInvokeTicks = stopwatch.ElapsedTicks - actionInvokeStart; Assert.IsTrue((actionInvokeTicks * 500) >= proxyInvokeTicks, "Invoke through the proxy should be within 100x the ticks to avoid reflection"); }
public async Task WeakEventHandler_Maintains_Weak_Reference_For_Target() { WeakEventHandlerProxy <EventArgs> proxy; { var subscriber = new CustomEventSubscriber <object>(); proxy = new WeakEventHandlerProxy <EventArgs>((Action <object, EventArgs>)subscriber.HandleEvent); Assert.AreEqual(subscriber, proxy.Target, "Proxy Target should be the event subscriber"); subscriber = null; } var waitCount = 0; var maximumWaitCount = 10; while (waitCount < maximumWaitCount) { waitCount++; if (proxy.Target == null) { break; } await Task.Delay(10); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } Assert.IsNull(proxy.Target, "Proxy Target should be garbage collected, proving it is a weak reference."); Assert.DoesNotThrow(() => proxy.RaiseEvent(null, null), "RaiseEvent should ignore the event if the target has been collected"); }
public void WeakEventHandlerProxy_Invokes_EventHandler_With_Null_Target() { var testHandler = new EventHandler(NoCaptureHandler); Assert.IsNull(testHandler.Target, $"{nameof(EventHandler)} under test should have a null {nameof(EventHandler.Target)}"); var testProxy = new WeakEventHandlerProxy <EventArgs>(testHandler); Assert.IsNull(testProxy.Target, $"{nameof(WeakEventHandlerProxy<EventArgs>)} should store null Target"); Assert.DoesNotThrow(() => testProxy.RaiseEvent(new object(), new EventArgs())); }
public void WeakEventHandlerProxy_RaiseEvent_Invokes_Given_EventHandler() { var handlerInvoked = false; var testHandler = new EventHandler((sender, e) => { handlerInvoked = true; }); var testProxy = new WeakEventHandlerProxy <EventArgs>(testHandler); Assert.AreEqual(testHandler.Target, testProxy.Target); testProxy.RaiseEvent(new object(), new EventArgs()); Assert.IsTrue(handlerInvoked, $"{nameof(WeakEventHandlerProxy<EventArgs>.RaiseEvent)} should invoke EventHandler from constructor"); }
public void WeakEventHandlerProxy_RaiseEvent_Invokes_With_Given_Sender_And_EventArgs() { var expectedSender = new object(); var expectedArgs = new EventArgs(); var handlerInvoked = false; var testHandler = new EventHandler((sender, args) => { handlerInvoked = true; Assert.AreEqual(expectedArgs, args); Assert.AreEqual(expectedSender, sender); }); var testProxy = new WeakEventHandlerProxy <EventArgs>(testHandler); testProxy.RaiseEvent(expectedSender, expectedArgs); Assert.IsTrue(handlerInvoked, $"{nameof(WeakEventHandlerProxy<EventArgs>.RaiseEvent)} should invoke EventHandler with given sender and EventArgs"); }
public void WeakEventHandler_RaiseEvent_Invokes_With_Generic_EventArgs() { var expectedSender = new object(); var expectedArgs = new CustomEventArgs <object> { EventData = new object() }; var handlerCalled = false; var testProxy = new WeakEventHandlerProxy <CustomEventArgs <object> >((Action <object, CustomEventArgs <object> >)((sender, e) => { handlerCalled = true; Assert.AreEqual(expectedSender, sender); Assert.AreEqual(expectedArgs, e); })); testProxy.RaiseEvent(expectedSender, expectedArgs); Assert.IsTrue(handlerCalled); }