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");
        }