<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Testing Events with Awesomeness</title>
	<atom:link href="http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/</link>
	<description></description>
	<lastBuildDate>Fri, 27 Aug 2010 20:21:49 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
	<item>
		<title>By: Derek Hammer</title>
		<link>http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/comment-page-1/#comment-257</link>
		<dc:creator>Derek Hammer</dc:creator>
		<pubDate>Sat, 05 Sep 2009 17:13:38 +0000</pubDate>
		<guid isPermaLink="false">http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/#comment-257</guid>
		<description>Since the code blocks apparently fail...

http://snipt.org/mJp</description>
		<content:encoded><![CDATA[<p>Since the code blocks apparently fail&#8230;</p>
<p><a href="http://snipt.org/mJp" rel="nofollow">http://snipt.org/mJp</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Derek Hammer</title>
		<link>http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/comment-page-1/#comment-256</link>
		<dc:creator>Derek Hammer</dc:creator>
		<pubDate>Sat, 05 Sep 2009 17:10:55 +0000</pubDate>
		<guid isPermaLink="false">http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/#comment-256</guid>
		<description>More awesomeness:

&lt;code&gt;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
using System.Collections;

namespace TestLibrary.Library
{
    public class AnotherEventTracker
        where TDelegate : class
    {
        public static implicit operator TDelegate(AnotherEventTracker tracker)
        {
            return tracker.Delegate;
        }

        public static implicit operator bool(AnotherEventTracker tracker)
        {
            return tracker.Verify();
        }

        private int _callCount;
        private List&lt;Func&gt; _checks;

        public AnotherEventTracker()
        {
            _checks = new List&lt;Func&gt;();

            var delegateMeta = typeof(TDelegate).GetMethod(&quot;Invoke&quot;);

            var delegateParams = delegateMeta
                .GetParameters()
                .Map(param =&gt; param.ParameterType)
                .Prepend(GetType())
                .ToArray();

            var invokedMethod = GetType().GetMethod(&quot;Invoked&quot;, BindingFlags.NonPublic &#124; BindingFlags.Instance &#124; BindingFlags.Public);
            var dynamicHandler = new DynamicMethod(&quot;&quot;, delegateMeta.ReturnType, delegateParams, GetType(), true);
            var generator = dynamicHandler.GetILGenerator();

            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Call, invokedMethod);
            generator.Emit(OpCodes.Ret);
            Delegate = dynamicHandler.CreateDelegate(typeof(TDelegate), this) as TDelegate;
        }

        public TDelegate Delegate
        {
            get;
            private set;
        }

        public AnotherEventTracker WasCalled()
        {
            _checks.Add(() =&gt; _callCount &gt; 0);
            return this;
        }

        public AnotherEventTracker Once()
        {
            return Exactly(1);
        }

        public AnotherEventTracker Twice()
        {
            return Exactly(2);
        }

        public AnotherEventTracker Exactly(int numberOfTimes)
        {
            _checks.Add(() =&gt; _callCount == numberOfTimes);
            return this;
        }

        public bool Verify()
        {
            return _checks.TrueForAll(func =&gt; func());
        }

        // called via the dynamic method
        private void Invoked()
        {
            _callCount++;
        }
    }
}

&lt;/code&gt;

I might make this into a post myself. This was pretty fun, making a closed  event tracker that looks like Moq.</description>
		<content:encoded><![CDATA[<p>More awesomeness:</p>
<p><code><br />
using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Text;<br />
using System.Reflection.Emit;<br />
using System.Reflection;<br />
using System.Collections;</p>
<p>namespace TestLibrary.Library<br />
{<br />
    public class AnotherEventTracker<br />
        where TDelegate : class<br />
    {<br />
        public static implicit operator TDelegate(AnotherEventTracker tracker)<br />
        {<br />
            return tracker.Delegate;<br />
        }</p>
<p>        public static implicit operator bool(AnotherEventTracker tracker)<br />
        {<br />
            return tracker.Verify();<br />
        }</p>
<p>        private int _callCount;<br />
        private List&lt;Func&gt; _checks;</p>
<p>        public AnotherEventTracker()<br />
        {<br />
            _checks = new List&lt;Func&gt;();</p>
<p>            var delegateMeta = typeof(TDelegate).GetMethod("Invoke");</p>
<p>            var delegateParams = delegateMeta<br />
                .GetParameters()<br />
                .Map(param =&gt; param.ParameterType)<br />
                .Prepend(GetType())<br />
                .ToArray();</p>
<p>            var invokedMethod = GetType().GetMethod("Invoked", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);<br />
            var dynamicHandler = new DynamicMethod("", delegateMeta.ReturnType, delegateParams, GetType(), true);<br />
            var generator = dynamicHandler.GetILGenerator();</p>
<p>            generator.Emit(OpCodes.Ldarg_0);<br />
            generator.Emit(OpCodes.Call, invokedMethod);<br />
            generator.Emit(OpCodes.Ret);<br />
            Delegate = dynamicHandler.CreateDelegate(typeof(TDelegate), this) as TDelegate;<br />
        }</p>
<p>        public TDelegate Delegate<br />
        {<br />
            get;<br />
            private set;<br />
        }</p>
<p>        public AnotherEventTracker WasCalled()<br />
        {<br />
            _checks.Add(() =&gt; _callCount &gt; 0);<br />
            return this;<br />
        }</p>
<p>        public AnotherEventTracker Once()<br />
        {<br />
            return Exactly(1);<br />
        }</p>
<p>        public AnotherEventTracker Twice()<br />
        {<br />
            return Exactly(2);<br />
        }</p>
<p>        public AnotherEventTracker Exactly(int numberOfTimes)<br />
        {<br />
            _checks.Add(() =&gt; _callCount == numberOfTimes);<br />
            return this;<br />
        }</p>
<p>        public bool Verify()<br />
        {<br />
            return _checks.TrueForAll(func =&gt; func());<br />
        }</p>
<p>        // called via the dynamic method<br />
        private void Invoked()<br />
        {<br />
            _callCount++;<br />
        }<br />
    }<br />
}</p>
<p></code></p>
<p>I might make this into a post myself. This was pretty fun, making a closed  event tracker that looks like Moq.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Shawn</title>
		<link>http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/comment-page-1/#comment-255</link>
		<dc:creator>Shawn</dc:creator>
		<pubDate>Fri, 04 Sep 2009 20:12:37 +0000</pubDate>
		<guid isPermaLink="false">http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/#comment-255</guid>
		<description>I like it!</description>
		<content:encoded><![CDATA[<p>I like it!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: jon</title>
		<link>http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/comment-page-1/#comment-254</link>
		<dc:creator>jon</dc:creator>
		<pubDate>Fri, 04 Sep 2009 19:59:15 +0000</pubDate>
		<guid isPermaLink="false">http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/#comment-254</guid>
		<description>The implicit operator is there as a convenience so you could actually assign your tracker to the event, rather than tracker.Delegate.
(e.g. &lt;code&gt;objectWithEvent.AwesomeEvent += tracker;&lt;/code&gt;)

It&#039;s definitely not needed, but an added convenience if you like it.</description>
		<content:encoded><![CDATA[<p>The implicit operator is there as a convenience so you could actually assign your tracker to the event, rather than tracker.Delegate.<br />
(e.g. <code>objectWithEvent.AwesomeEvent += tracker;</code>)</p>
<p>It&#8217;s definitely not needed, but an added convenience if you like it.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Shawn</title>
		<link>http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/comment-page-1/#comment-253</link>
		<dc:creator>Shawn</dc:creator>
		<pubDate>Fri, 04 Sep 2009 18:59:58 +0000</pubDate>
		<guid isPermaLink="false">http://jonfuller.codingtomusic.com/2009/09/03/testing-events-with-awesomeness/#comment-253</guid>
		<description>Can you explain why the implicit operator is needed in EventTracker?</description>
		<content:encoded><![CDATA[<p>Can you explain why the implicit operator is needed in EventTracker?</p>
]]></content:encoded>
	</item>
</channel>
</rss>
