<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C0QAR3k_fyp7ImA9WhRWEks.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075</id><updated>2011-12-30T08:09:06.747-08:00</updated><title>Jolt.NET Development Blog</title><subtitle type="html">Feature and development news for the Jolt.NET productivity libraries.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://joltdev.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/JoltNetDevelopmentBlog" /><feedburner:info uri="joltnetdevelopmentblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DEcFQnY8fCp7ImA9Wx5QE0g.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-1934655669068879355</id><published>2010-09-01T08:46:00.001-07:00</published><updated>2010-09-01T08:46:53.874-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-01T08:46:53.874-07:00</app:edited><title>Verifying the Equality Semantics of a Type</title><content type="html">&lt;p&gt;My most recent contribution to Jolt.NET is implementing a set of assertion classes that verify if a type correctly implements equality semantics.&amp;nbsp; This is a unit testing task that is generally ignored, only because implementations of &lt;font face="Courier New"&gt;Object.Equals()&lt;/font&gt; are usually straightforward and implemented in terms of other types that meet this critieria.&lt;/p&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;When implementing an equality operator, you must make sure that it satisfies the following axioms.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div&gt;Symmetry:&amp;nbsp; Equals(x,y) == Equals(y,x)&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Transitivity:&amp;nbsp; Equals(x,z) == true if and only if (Equals(x,y) &amp;amp; Equals(y,z)) == true&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Reflexivity:&amp;nbsp; Equals(x,x) == true&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Hash-code:&amp;nbsp; Equals(x,y) =&amp;gt; GetHashCode(x) == GetHashCode(y)&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;I&amp;#39;ve omitted the other axiom requirements for equality, which are described by the &lt;a href="http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx" id="nvjd" title="MSDN documentation"&gt;MSDN documentation&lt;/a&gt; for &lt;font face="Courier New"&gt;Object.Equals()&lt;/font&gt;.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;Jolt.NET provides the type &lt;font face="Courier New"&gt;EqualityAxiomAssertion&amp;lt;T&amp;gt;&lt;/font&gt; to validate the implementations of &lt;font face="Courier New"&gt;T.Equals()&lt;/font&gt; according to the prescribed axioms.&amp;nbsp; You may use the type as follows.&lt;/p&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;pre class="brush:csharp"&gt;class TypeToValidate&lt;br /&gt;{&lt;br /&gt;    public override bool Equals(object other)&lt;br /&gt;    {&lt;br /&gt;        return other is TypeToValidate &amp;amp;&amp;amp;&lt;br /&gt;               (other as TypeToValidate).m_name.Equals(m_name);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public string m_name;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class TypeFactory : IArgumentFactory&amp;lt;TypeToValidate&amp;gt;&lt;br /&gt;{&lt;br /&gt;    public TypeFactory Create()&lt;br /&gt;    {&lt;br /&gt;        return new TypeToValidate() { m_name = &amp;quot;Hello world!&amp;quot; };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void Modify(ret TypeToValdidate instance)&lt;br /&gt;    {&lt;br /&gt;        instance.m_name = &amp;quot;Goodbye world!&amp;quot;;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class TestFixture()&lt;br /&gt;{&lt;br /&gt;    void Test()&lt;br /&gt;    {&lt;br /&gt;        EqualityAxiomAssertion&amp;lt;TypeToValidate&amp;gt; assertion =&lt;br /&gt;            new EqualityAxiomAssertion&amp;lt;TypeToValidate&amp;gt;(new TypeFactory());&lt;br /&gt;&lt;br /&gt;        AssertionResult assertionResult = assertion.Validate();&lt;br /&gt;        System.Diagnostics.Debug.Assert(assertionResult.Result, assertionResult.Message);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;font face="Courier New"&gt;IArgumentFactory&amp;lt;T&amp;gt;&lt;/font&gt; is required by the assertion type since it needs to be able to create and modify instances of the type that is being verified.&amp;nbsp; For instance, the transitivity axiom requires three distinct instances, and hash-code verification must modify an instance and verify that the resulting hash-code has changed.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;There are many representations of an equality operator in .NET, some of which are &lt;font face="Courier New"&gt;Object.Equals()&lt;/font&gt;, &lt;font face="Courier New"&gt;IEquatable&amp;lt;T&amp;gt;&lt;/font&gt;, &lt;font face="Courier New"&gt;IComparable&amp;lt;T&amp;gt;&lt;/font&gt;, and &lt;font face="Courier New"&gt;IEqualityComparer&amp;lt;T&amp;gt;&lt;/font&gt;.&amp;nbsp; In addition to &lt;font face="Courier New"&gt;EqualityAxiomAssertion&amp;lt;T&amp;gt;&lt;/font&gt;, Jolt.NET also provides the &lt;font face="Courier New"&gt;EqualtableAxiomAssertion&amp;lt;T&amp;gt;&lt;/font&gt;, &lt;font face="Courier New"&gt;ComparableAxiomAssertion&amp;lt;T&amp;gt;&lt;/font&gt;, and &lt;font face="Courier New"&gt;EqualityComparerAxiomAssertion&amp;lt;T&amp;gt;&lt;/font&gt; to verify implementations of the aforementioned equality interfaces, with similar usage semantics.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;Jolt.NET also provides a wrapper to these assertion types for straightforward integration with NUnit and Visual Studio&amp;#39;s unit test environment.&amp;nbsp; An example of how to use a wrapped &lt;font face="Courier New"&gt;EqualityAxiomAssertion&amp;lt;T&amp;gt;&lt;/font&gt; in these environments follows.&amp;nbsp; Note that the remaining assertion types are also wrapped by similar methods and/or constructs.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;pre class="brush: csharp"&gt;class TestFixture()&lt;br /&gt;{&lt;br /&gt;    // Visual Studio assertion model&lt;br /&gt;    [TestMethod]&lt;br /&gt;    public void EqualityAxiomTest()&lt;br /&gt;    {&lt;br /&gt;        AxiomAssert.Equality(new TypeFactory());&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[TestFixture]&lt;br /&gt;class NUnitFixture&lt;br /&gt;{&lt;br /&gt;    // NUnit assertion model&lt;br /&gt;    [Test]&lt;br /&gt;    public void EqualityAxiomTest()&lt;br /&gt;    {&lt;br /&gt;        // verbose constraint model&lt;br /&gt;        Assert.That(typeof(TypeToValidate), new EqualityAxiomConstraint&amp;lt;TypeToValidate&amp;gt;(new TypeFactory()));&lt;br /&gt;	&lt;br /&gt;        // syntax-helper constraint model&lt;br /&gt;        Assert.That(typeof(TypeToValidate), Implements.EqualityAxiom(new TypeFactory()));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;The astute reader will notice that there is some duplication in the syntax for invoking the constraint.&amp;nbsp; Specifically, the type information is duplicated.&amp;nbsp; In fact, the first argument of the assertion is not used by the constraint at all -- it is merely present for readability when using a syntax helper.&amp;nbsp; Ideally, I would have liked to have used a syntax similar to the following.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;pre class="brush: csharp"&gt;[Test]&lt;br /&gt;public void EqualityAxiomTest()&lt;br /&gt;{&lt;br /&gt;    Assert.That&amp;lt;TypeToValidate&amp;gt;(Implements.EqualityAxiom(new TypeFactory()));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;However, this is not possible for several reasons.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div&gt;NUnit constraints are designed to compare an actual value against an expected value; an argument-less constraint is not possible.&lt;/div&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;div&gt;This notiion is somewhat incompatible with the axiom assertion since the assertion is validating a property of a generic type argument.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;The assertion could have been designed to be non-generic and operate on &lt;font face="Courier New"&gt;System.Type&lt;/font&gt;, but that implementation would be more cumbersome&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;div&gt;An extension method on Assert is not possible since Assert methods are static.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;Another option is to use the factory instance as the argument passed to the constraint, as in the following example.&amp;nbsp; However, while this option makes sense from an implementation standpoint, it suffers greatly in readability as a factory instance is not what is being asserted upon.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;pre class="brush: csharp"&gt;[Test]&lt;br /&gt;public void EqualityAxiomTest()&lt;br /&gt;{&lt;br /&gt;    // verbose constraint syntax&lt;br /&gt;    Assert.That(new TypeFactory(), new EqualityAxiomConstraint&amp;lt;TypeToValidate&amp;gt;());&lt;br /&gt;&lt;br /&gt;    // syntax-helper constraint syntax.&lt;br /&gt;    Assert.That(new TypeFactory(), Implements.EqualityAxiom&amp;lt;TypeToValidate&amp;gt;());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;The documentation for these classes will be posted to the docs section shortly, and in the future, support will be added for the non-generic interfaces &lt;font face="Courier New"&gt;IEquatable&lt;/font&gt;, &lt;font face="Courier New"&gt;IComparable&lt;/font&gt;, &lt;font face="Courier New"&gt;IEqualityComparer&lt;/font&gt;.&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-1934655669068879355?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PMCae4fUU4LiYJW752Oygx6KajM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PMCae4fUU4LiYJW752Oygx6KajM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PMCae4fUU4LiYJW752Oygx6KajM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PMCae4fUU4LiYJW752Oygx6KajM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Mwf7xoe6EgQ:atKCFBmZxDU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Mwf7xoe6EgQ:atKCFBmZxDU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=Mwf7xoe6EgQ:atKCFBmZxDU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Mwf7xoe6EgQ:atKCFBmZxDU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/Mwf7xoe6EgQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/1934655669068879355/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=1934655669068879355" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/1934655669068879355?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/1934655669068879355?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/Mwf7xoe6EgQ/verifying-equality-semantics-of-type.html" title="Verifying the Equality Semantics of a Type" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2010/09/verifying-equality-semantics-of-type.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcMSXo-eyp7ImA9Wx5SEk0.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-7629579071531279854</id><published>2010-08-07T09:50:00.001-07:00</published><updated>2010-08-07T09:54:48.453-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-07T09:54:48.453-07:00</app:edited><title>Return to Developing Jolt.NET</title><content type="html">Good day readers!&lt;br&gt;&lt;br&gt;&lt;div&gt;Over the past few months, I haven&amp;#39;t spend any time time on the Jolt.NET project as I&amp;#39;ve experienced several life-changes that require the reallocation of the limited time I have to spend on hobbies. &amp;nbsp;My daughter was born in February and she has brought much joy to my family. &amp;nbsp;As with most newborns, she is a handful, and requires near-constant supervision. &amp;nbsp;I&amp;#39;ve also recently changed roles within my firm, and my new responsibilities require more of my time. &amp;nbsp;Recently, things have started to become more routine and so I&amp;#39;m hoping to return to the Jolt.NET project and complete some pending items of importance. &amp;nbsp;&lt;/div&gt;&lt;br&gt;&lt;u&gt;Non-deterministic FSM Support&lt;/u&gt;&lt;br&gt;&lt;br&gt;&lt;div&gt;One such item of importance is the support of &lt;a href="http://jolt.codeplex.com/workitem/3450" id="u:-w" title="enumerating non-deterministic automata"&gt;enumerating non-deterministic automata&lt;/a&gt;. &amp;nbsp;When implementing this feature, I realized that I needed to introduce a breaking change into the generalization of an FSM enumerator as the &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;IFsmEnumerator&amp;lt;T&amp;gt;&lt;/font&gt; interface conveys that all enumerator implementations return one state as part of a transition. &amp;nbsp;Since this is not true for non-deterministic FSMs, the interface is changed to the following.&lt;/div&gt;&lt;br&gt;&lt;pre class="brush: csharp"&gt;public interface IFsmEnumerator&amp;lt;TAlphabet&amp;gt;&lt;br /&gt;{&lt;br /&gt;	bool Next(TAlphabet inputSymbol);&lt;br /&gt;	string CurrentState { get; }&lt;br /&gt;	IEnumerable&amp;lt;string&amp;gt; CurrentStates { get; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br&gt; The main differences in this interface revision are the semantics of the &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;CurrentState&lt;/font&gt; and (new) &lt;font face="&amp;#39;courier new&amp;#39;"&gt;CurrentStates&lt;/font&gt; properties for different types of enumerators. &amp;nbsp;When the enumerator is reading a deterministic FSM, &lt;font face="&amp;#39;courier new&amp;#39;"&gt;CurrentState&lt;/font&gt; refers to the current enumeration state, and &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;CurrentStates&lt;/font&gt; is a collection containing a single reference to CurrentStates. &amp;nbsp;However, when the enumerator is reading a non-deterministic FSM, &lt;font face="&amp;#39;courier new&amp;#39;"&gt;CurrentStates&lt;/font&gt; contains the current enumeration states (which may be more than one) and &lt;font face="&amp;#39;courier new&amp;#39;"&gt;CurrentState&lt;/font&gt; refers to the first element of the &lt;font face="&amp;#39;courier new&amp;#39;"&gt;CurrentStates&lt;/font&gt; collection.&lt;br&gt;&lt;br&gt;&lt;div&gt;The consequences of this interface change propagate to the following &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;FiniteStateMachine&amp;lt;T&amp;gt;&lt;/font&gt; methods.&lt;/div&gt;&lt;br&gt;&lt;pre class="brush: csharp"&gt;public class FiniteStateMachine&amp;lt;TAlphabet&amp;gt;&lt;br /&gt;{&lt;br /&gt;	// ... other members omitted for brevity ...&lt;br /&gt;&lt;br /&gt;	public virtual IFsmEnumerator&amp;lt;TAlphabet&amp;gt; CreateStateEnumerator(EnumerationType type, string startState);&lt;br /&gt;&lt;br /&gt;	public virtual ConsumptionResult&amp;lt;TAlphabet&amp;gt; Consume(EnumerationType type, IEnumerable&amp;lt;TAlphabet&amp;gt; inputSymbols);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br&gt;&lt;div&gt;When creating an enumerator via the &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;CreateStateEnumerator()&lt;/font&gt; method, the type of enumeration must be specified. &amp;nbsp;Consequently, the type of enumeration must also be specified when consuming a set of input symbols via the &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;Consume()&lt;/font&gt; method.&lt;/div&gt;&lt;br&gt;&lt;div&gt;Finally, the &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;ConsumptionResult&amp;lt;T&amp;gt;.LastState&lt;/font&gt; property is replaced with the &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;LastStates&lt;/font&gt; property, returning a collection of states denoting the set of states viewed immediately prior to completing the symbol consumption.&lt;/div&gt;&lt;br&gt;&lt;pre class="brush: csharp"&gt;public sealed class ConsumptionResult&lt;br /&gt;{&lt;br /&gt;	// ... other members omitted for brevity ...&lt;br /&gt;&lt;br /&gt;	public IEnumerable LastStates { get; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br&gt;&lt;div&gt;&lt;u&gt;ReadOnlyDictionary&amp;lt;T,U&amp;gt; Support&lt;/u&gt;&lt;/div&gt;&lt;br&gt;&lt;div&gt;Creating a read-only &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;IDictionary&amp;lt;T,U&amp;gt;&lt;/font&gt; collection is a fairly straight-forward task, but this analog to &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms132474.aspx" id="x.gj" title="ReadOnlyCollection&amp;lt;T&amp;gt;"&gt;ReadOnlyCollection&amp;lt;T&amp;gt;&lt;/a&gt;&lt;/font&gt; is surprisingly missing from .NET 4.0. &amp;nbsp;I have an immediate need for this type in a side project and thus will include a complete implementation it in the library.&lt;/div&gt;&lt;br&gt;&lt;div&gt;For reference, &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;ReadOnlyCollection&amp;lt;T&amp;gt;&lt;/font&gt; is an adaptor to &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;IList&amp;lt;T&amp;gt;&lt;/font&gt; that prevents a caller from changing the internal structure of the adapted collection (i.e. adding/removing elements). &amp;nbsp;When a method to change the structure of the collection is called, a &lt;font face="&amp;#39;Courier New&amp;#39;"&gt;NotSupportException&lt;/font&gt; is raised and the collection remains unmodified.&lt;/div&gt;&lt;br&gt;&lt;u&gt;Honoring Existing Interfaces on Generated Types&lt;/u&gt;&lt;br&gt;&lt;br&gt;&lt;div&gt;When first developing Jolt.NET, I focused on a &lt;a href="http://jolt.codeplex.com/wikipage?title=Jolt.Testing.CodeGeneration.Proxy&amp;amp;referringTitle=Jolt.Testing" id="tnuy" title="tool"&gt;tool&lt;/a&gt; that will generate an interface and proxy type to any other type. &amp;nbsp;The goal of this task was to facilitate dependency injection for static types as this is a common problem to tackle when unit testing with existing, non-modifiable static types. &amp;nbsp;Note that the current implementation doesn&amp;#39;t restrict you from generating the interface/proxy pair for just static types.&lt;/div&gt;&lt;br&gt;&lt;div&gt;One challenge that arose during the implementation was dealing with propagating public interface implementations to the proxy/interface pair. &amp;nbsp;This made a lot of sense since you could use the generated types with methods that accept the abstraction, and everything would just work. &amp;nbsp;Unfortunately, I found this to be very difficult at the time and &lt;a href="http://jolt.codeplex.com/workitem/27" id="rp:q" title="postponed"&gt;postponed&lt;/a&gt; implementing it.&lt;/div&gt;&lt;br&gt; I believe I now have a good algorithm to solve this problem (as described in this &lt;a href="http://jolt.codeplex.com/Thread/View.aspx?ThreadId=82257" id="u:25" title="forum post"&gt;forum post&lt;/a&gt;), and will to try to implement it.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-7629579071531279854?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Xg6uwQxBoCugj8TL4rIKafsWZhw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Xg6uwQxBoCugj8TL4rIKafsWZhw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Xg6uwQxBoCugj8TL4rIKafsWZhw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Xg6uwQxBoCugj8TL4rIKafsWZhw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=h8XIhlSiEmM:c4Dx5dIHwk0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=h8XIhlSiEmM:c4Dx5dIHwk0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=h8XIhlSiEmM:c4Dx5dIHwk0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=h8XIhlSiEmM:c4Dx5dIHwk0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/h8XIhlSiEmM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/7629579071531279854/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=7629579071531279854" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/7629579071531279854?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/7629579071531279854?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/h8XIhlSiEmM/return-to-developing-joltnet.html" title="Return to Developing Jolt.NET" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2010/08/return-to-developing-joltnet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMFRHwzeyp7ImA9WxBXF0g.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-4981031941262428339</id><published>2010-01-28T23:33:00.001-08:00</published><updated>2010-01-28T23:33:35.283-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-28T23:33:35.283-08:00</app:edited><title>Circular Collections and Enumeration</title><content type="html">Sunday evening I committed revision &lt;a id="m4b2" href="http://jolt.codeplex.com/SourceControl/changeset/view/33654" title="#33654"&gt;#33654&lt;/a&gt;, which includes the first additions to the Jolt.Collections library: circular lists and enumerators. &amp;nbsp;A complete overview of the features enabled by these types, including usage examples, is available on the library's&amp;nbsp;&lt;a id="qnyz" href="http://jolt.codeplex.com/wikipage?title=Jolt.Collections.Circular&amp;amp;referringTitle=Jolt.Collections" title="documentation page"&gt;documentation page&lt;/a&gt;. &amp;nbsp;In this post, I will discuss some of the implementation decisions went into producing these types, as well as give a brief overview of how the new types work.&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span style="font-weight: normal;"&gt;&lt;u&gt;Adaptors v.s. Collections&lt;/u&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span style="font-weight: normal;"&gt;&lt;br&gt;The goal of the initial library release was to support three data types:&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;An enumerator capable of enumerating any collection in a circular manner&lt;/li&gt;&lt;li&gt;A circular list, with semantics similar to the &lt;font class="Apple-style-span" face="'Courier New'"&gt;System.Collections.Generic.List&lt;/font&gt; class&lt;/li&gt;&lt;li&gt;A circular linked list, with semantics similar to the&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;System.Collections.Generic.LinkedList&lt;/font&gt;&amp;nbsp;class&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;All three of these types were to be implemented as adaptors, providing circular-list semantics as a pseudo-"view" of the underlying collection. &amp;nbsp;In this view however, insertions and removals would indeed be propagated to the underlying collection wheres as other operations remained read-only. &amp;nbsp;In order to keep the implementation simple and straightforward (maintaining as many forwarding methods as possible), I decided to implement the circular collections with copy construction semantics (i.e. no adaptation), and in terms of their&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;List&lt;/font&gt;&amp;nbsp;and &lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedList&lt;/font&gt; counterparts. &amp;nbsp;It didn't seem right to provide an adaptor whose operations may or may not transform the underlying collection. &amp;nbsp;Furthermore, the implementation of the&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Shift&lt;/font&gt;&amp;nbsp;operator for a linked list (see below), complicates the implementation of other operations when implemented as a non-destructive operator.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;Cyclical v.s. Circular Collections&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Another trade-off that was made was in choosing to implement cyclical collections, or the less-general circular collections (cyclical collections join the last collection element to any preceding collection element). &amp;nbsp;The challenge with a cyclical collection was in using an existing enumerator to implement the enumeration algorithm, again aiming at minimizing the amount of code to rewrite (e.g. version checking, storing collection element references, etc...). &amp;nbsp;With a cyclical collection, the enumerator needs to reset itself to an arbitrary position in the underlying collection, and unfortunately, there is no good way to do this in a generic fashion -- the .NET enumerator interface provides no such functionality. &amp;nbsp;The best we could do is store the reference to the start of the cycle and then implicitly enumerate to that element when enumerating beyond the end of the collection. &amp;nbsp;Clearly, this performs very poorly for large collections.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;In the end, I chose circular collections for simplicity. &amp;nbsp;However, in retrospect, implementing a cyclical collection would not be too difficult if I chose not to reuse certain aspects of the&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;List&lt;/span&gt;&amp;nbsp;or&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;LinkedList&lt;/span&gt;&amp;nbsp;collections and their enumerators.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;u&gt;Circular Enumerator&lt;/u&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularEnumerator&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;is an adaptor class accepting an&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;IEnumerator&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;instance at construction time. &amp;nbsp;The enumerator forwards calls to the underlying enumerator except that when enumeration progresses beyond the last collection element (i.e. &lt;/span&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Next()&lt;/font&gt;&lt;/span&gt;&lt;span style="font-weight: normal"&gt; returns false), the underlying enumerator is reset and moved to the first collection element.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;It goes without saying that you should not use a circular enumerator within a &lt;font class="Apple-style-span" face="'Courier New'"&gt;foreach&lt;/font&gt;&amp;nbsp;loop unless there is an explicit break condition with the loop body.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;Circular List&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularList&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;is effectively a &lt;font class="Apple-style-span" face="'Courier New'"&gt;List&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;with circular list semantics. &amp;nbsp;That is, the &lt;font class="Apple-style-span" face="'Courier New'"&gt;GetEnumerator()&lt;/font&gt;&amp;nbsp;method returns a&amp;nbsp;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularEnumerator&amp;lt;T&amp;gt;&lt;/font&gt;, and given indexes for indexing operations are allowed to exceed the bounds of the collection (for positive indexes). &amp;nbsp;Modular arithmetic translates a user-specified index to the correct internal&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: 'Courier New'"&gt;List&lt;/span&gt;&amp;nbsp;index.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New'"&gt;CircularList&amp;lt;T&amp;gt;&lt;/span&gt;&amp;nbsp;also implements &lt;font class="Apple-style-span" face="'Courier New'"&gt;operator&amp;gt;&amp;gt;()&lt;/font&gt; and &lt;font class="Apple-style-span" face="'Courier New'"&gt;operator&amp;lt;&amp;lt;()&lt;/font&gt;, which effectively "rotates" the circular list, changing the sequence of elements. &amp;nbsp;For instance, if a collection containing the ordered elements {10, 1, 5, 58, 32} is forward-shifted by two elements, the resulting collection contains the elements {5, 58, 32, 10, 1}. &amp;nbsp;Since&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;List&amp;lt;T&amp;gt;&lt;/span&gt;&amp;nbsp;stores its elements in a contiguous memory block,&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;CircularList&amp;lt;T&amp;gt;&lt;/span&gt;&amp;nbsp;implements shifting as a "view" on the underlying collection to avoid the copying or moving of collection elements. &amp;nbsp;A virtual head-index is maintained, and user-specified indexes are adjusted accordingly.&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;Circular Linked List&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularLinkedList&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;is effectively a &lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedList&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;with circular list semantics. &amp;nbsp;That is, the&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;GetEnumerator()&lt;/span&gt;&amp;nbsp;method returns a&amp;nbsp;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularEnumerator&amp;lt;T&amp;gt;&lt;/font&gt;, and the node-access methods return a&amp;nbsp;&lt;b&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularLinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;&amp;nbsp;object. &amp;nbsp;Similarly,&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularLinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt; encapsulates a &lt;/span&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;and provides circular navigation semantics through its &lt;/span&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Next()&lt;/font&gt;&lt;/span&gt; &lt;/b&gt;and &lt;font class="Apple-style-span" face="'Courier New'"&gt;Previous()&lt;/font&gt;&amp;nbsp;methods.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;On a side note, the .NET 3.5 implementation of&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedList&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;is internally implemented as a circular linked list. &amp;nbsp;The last collection element connected to the first element, and because of this, the implementation of certain list operations is simplified. &amp;nbsp;Unfortunately, this implementation detail is completely hidden from the user, and can not be leveraged by the&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularLinkedList&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;implementation.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Much like&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;CircularList&amp;lt;T&amp;gt;&lt;/span&gt;, &lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularLinkedList&amp;lt;T&amp;gt;&lt;/font&gt; also implements&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;operator&amp;gt;&amp;gt;()&lt;/font&gt;&amp;nbsp;and&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;operator&amp;lt;&amp;lt;()&lt;/font&gt;. &amp;nbsp;However, since &lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedList&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;doesn't provide direct-access to an arbitrary element, each call to a shift operation transforms the underlying collection. &amp;nbsp;An optimization in the shift algorithm places an upper-bound on the total number of shifts to &lt;b&gt;N/2&lt;/b&gt;, where &lt;b&gt;N&lt;/b&gt; is the size of the collection. &amp;nbsp;We accomplish this by noting that a forward shift of &lt;b&gt;k&lt;/b&gt; elements is identical to a backwards shift of &lt;b&gt;N - k&lt;/b&gt; elements. &amp;nbsp;Hence the maximum number of shifts occur when &lt;b&gt;k = N - k&lt;/b&gt;, or &lt;b&gt;k = N/2&lt;/b&gt;.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;Circular Linked List Node&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;CircularLinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;encapsulates a&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;, is used for inserting new nodes into the collection, and representing existing nodes in the collection. &amp;nbsp;Since&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&amp;nbsp;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;exposes the list in which the node is contained, &lt;b&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Circular&lt;/font&gt;&lt;/span&gt;&lt;span style="font-weight: normal"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;must hide this list, but expose the circular list for consistency. &amp;nbsp;Furthermore,&amp;nbsp;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Circular&lt;/font&gt;&lt;/span&gt;&lt;span style="font-weight: normal"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt; references are never stored in a container; they are created on-demand. &amp;nbsp;Thus, it is possible to create two different&amp;nbsp;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Circular&lt;/font&gt;&lt;/span&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;object for the same underlying node. &amp;nbsp;To minimize the impact of this draw-back,&amp;nbsp;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal"&gt;&lt;b&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Circular&lt;/font&gt;&lt;/span&gt;&lt;span style="font-weight: normal"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;LinkedListNode&amp;lt;T&amp;gt;&lt;/font&gt;&amp;nbsp;implements &lt;/span&gt;&lt;span style="font-weight: normal;"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;IEqualityComparer&amp;lt;T&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;which performs a reference comparison on each object's underlying nodes.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-4981031941262428339?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/YxP5ceW8CU0c12A-8QBwPWY2KCE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YxP5ceW8CU0c12A-8QBwPWY2KCE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/YxP5ceW8CU0c12A-8QBwPWY2KCE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YxP5ceW8CU0c12A-8QBwPWY2KCE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Rj98KnS2UMc:tvJVXYGFcUM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Rj98KnS2UMc:tvJVXYGFcUM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=Rj98KnS2UMc:tvJVXYGFcUM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Rj98KnS2UMc:tvJVXYGFcUM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/Rj98KnS2UMc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/4981031941262428339/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=4981031941262428339" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/4981031941262428339?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/4981031941262428339?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/Rj98KnS2UMc/circular-collections-and-enumeration.html" title="Circular Collections and Enumeration" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2010/01/circular-collections-and-enumeration.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUMQH85fSp7ImA9WxBTEkw.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-2957127719983404233</id><published>2009-12-07T12:38:00.001-08:00</published><updated>2009-12-07T12:38:01.125-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-07T12:38:01.125-08:00</app:edited><title>Jolt.NET 0.4 Release and Future Features</title><content type="html">Good day readers!&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Yesterday I completed the final &lt;a id="fcku" href="http://jolt.codeplex.com/WorkItem/AdvancedList.aspx" title="work items"&gt;work items&lt;/a&gt; for Jolt.NET 0.4 and produced the release, available for download at &lt;a id="osof" href="http://jolt.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=32175" title="CodePlex"&gt;CodePlex&lt;/a&gt;. &amp;nbsp;As mentioned earlier, this release was primarily a maintenance release aimed at addressing some long standing code quality issues and external library upgrades. &amp;nbsp;However, the release does contain some new features, summarized below.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Jolt.NET XML Assertions are now compatible with the Visual Studio test environment, through a set of &lt;a id="hb6i" href="http://jolt.codeplex.com/wikipage?title=Jolt.Testing.Assertions.XML.Adaptors&amp;amp;referringTitle=Jolt.Testing" title="adapter types"&gt;adapter types&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a id="e0dl" href="http://jolt.codeplex.com/wikipage?title=Jolt.XmlDocComments&amp;amp;referringTitle=Jolt" title="XML doc comment parsing"&gt;XML doc comment parsing&lt;/a&gt; for &lt;font class="Apple-style-span" face="'Courier New'"&gt;MethodInfo&lt;/font&gt; objects that refer to an operator&lt;/li&gt;&lt;li&gt;Generated &lt;a id="i-yc" href="http://jolt.codeplex.com/wikipage?title=Jolt.Testing.CodeGeneration.Proxy&amp;amp;referringTitle=Jolt.Testing" title="proxy assemblies"&gt;proxy assemblies&lt;/a&gt; may now be signed programatically or via XML application configuration&lt;/li&gt;&lt;li&gt;All Jolt.NET assemblies are built with a strong name, enabling integrity verification and use with other strong-name assemblies&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;For more information on these features, please refer to the Jolt.NET library &lt;a id="ge3y" href="http://jolt.codeplex.com/documentation" title="documentation"&gt;documentation&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;The feature list for next release of Jolt.NET remains undefined as I am planning to take on a commercial project that will use the Jolt.NET libraries. &amp;nbsp;Jolt.NET features will be fueled by the requirements of this new project, but features won't be added unless they are sensible additions for a library. &amp;nbsp;I do maintain a short-list of potential feature work, and will say that the following features are likely to make the cut for the next Jolt.NET release.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Verification of the equality axiom, for implementations of &lt;font class="Apple-style-span" face="'Courier New'"&gt;Object.Equals&lt;/font&gt; and &lt;font class="Apple-style-span" face="'Courier New'"&gt;IEquatable&amp;lt;T&amp;gt;&lt;/font&gt;&lt;/li&gt;&lt;li&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;XmlEqualityAssertion&lt;/font&gt; and &lt;font class="Apple-style-span" face="'Courier New'"&gt;XmlEquivalencyAssertion&lt;/font&gt; implementations that accept XPath statements&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Do you have any feature requests? &amp;nbsp;If so, please post them on the &lt;a id="u:xq" href="http://jolt.codeplex.com/WorkItem/List.aspx" title="work item page"&gt;work item page&lt;/a&gt;, or vote-up existing tasks!&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-2957127719983404233?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/FbylhN5a4f7TtEzz1AATnNWyz84/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FbylhN5a4f7TtEzz1AATnNWyz84/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/FbylhN5a4f7TtEzz1AATnNWyz84/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FbylhN5a4f7TtEzz1AATnNWyz84/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=FsyiuOqsXko:5-CeR_QfRCk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=FsyiuOqsXko:5-CeR_QfRCk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=FsyiuOqsXko:5-CeR_QfRCk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=FsyiuOqsXko:5-CeR_QfRCk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/FsyiuOqsXko" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/2957127719983404233/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=2957127719983404233" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/2957127719983404233?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/2957127719983404233?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/FsyiuOqsXko/joltnet-04-release-and-future-features.html" title="Jolt.NET 0.4 Release and Future Features" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/12/joltnet-04-release-and-future-features.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIDRX4yeSp7ImA9WxNVFkg.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-7255143156116636721</id><published>2009-10-26T21:19:00.001-07:00</published><updated>2009-10-27T07:09:34.091-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-27T07:09:34.091-07:00</app:edited><title>Limitations to XML Doc Comment Parsing</title><content type="html">Hello everyone!&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;I've been working on improving the support for &lt;a id="cum:" href="http://jolt.codeplex.com/wikipage?title=Jolt.XmlDocComments&amp;amp;referringTitle=Jolt" title="XML doc comment"&gt;XML doc comment&lt;/a&gt; queries with metadata types, but came across some limitations in the reflection API that have hindered my progress. &amp;nbsp;Specifically, I've been trying to add support for retrieving doc comments for methods containing a function pointer as a parameter, and methods containing a parameter that has been decorated with an optional or required custom modifier. &amp;nbsp;Unfortunately, given the current state of the reflection API (for which I will elaborate upon below), I don't believe that I can implement these features and achieve a general solution that works for all inputs.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;&lt;span style="text-decoration: none;"&gt;&lt;a id="s40e" href="http://jolt.codeplex.com/WorkItem/View.aspx?WorkItemId=3955" title="Function Pointer Parameters"&gt;Function Pointer Parameters&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;The goal of this feature is to be able to retrieve the XML comments as given in the following code example.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;pre class="brush: c++"&gt;public ref class T&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    /// &amp;lt;summary/&amp;gt;&lt;br /&gt;    /// &amp;lt;param name="param"&amp;gt;A function pointer of managed types&amp;lt;/param&amp;gt;&lt;br /&gt;    void FnPtrMethod(String^ (*param)(TimeSpan, DateTime, array&amp;lt;int&amp;gt;^)) { }&lt;br /&gt;};&lt;/pre&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Since a function pointer is a native C++ entity, it is not recognized by the CLR and consequently I don't believe it to be possible to adequately represent it with a metadata object. &amp;nbsp;Given the method&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;FnPtrMethod&lt;/font&gt; above, the managed type of its sole parameter &lt;font class="Apple-style-span" face="'Courier New'"&gt;param&lt;/font&gt; is rendered by the reflection API as &lt;font class="Apple-style-span" face="'Courier New'"&gt;&lt;a id="bu0o" href="http://msdn.microsoft.com/en-us/library/system.intptr(VS.90).aspx" title="System.IntPtr"&gt;System.IntPtr&lt;/a&gt;&lt;/font&gt;. &amp;nbsp;This is understandable sense since the function pointer is really a raw native pointer to the address of executable code. &amp;nbsp;It makes no difference that its arguments are managed types, since the type that encompasses them is not managed.  If all we have to work with is an&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;IntPtr&lt;/span&gt;&amp;nbsp;instance, then it is impossible to infer that the&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;IntPtr&lt;/span&gt;&amp;nbsp;is really a function pointer and fetch its managed arguments for processing.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;I'm fairly confident that my analysis is correct, but in the hope of being wrong I've started a &lt;a id="f9-3" href="http://stackoverflow.com/questions/1608200/is-it-possible-to-infer-that-a-parameterinfo-object-refers-to-a-function-pointer" title="discussion"&gt;discussion&lt;/a&gt; on StackOverflow just to be sure. &amp;nbsp;If you know the trick to get this to work, please respond to this blog entry or to the discussion on StackOverflow.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;&lt;span style="text-decoration: none;"&gt;&lt;a id="mddu" href="http://jolt.codeplex.com/WorkItem/View.aspx?WorkItemId=5011" title="Optional and Required Custom Modifiers"&gt;Optional and Required Custom Modifiers&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;The goal of this feature is to be able to retrieve the XML comments as given in the following code example.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;pre class="brush: c++"&gt;public ref class T&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    /// &amp;lt;summary/&amp;gt;&lt;br /&gt;    /// &amp;lt;param name="x"&amp;gt;modopt&amp;lt;/param&amp;gt;&lt;br /&gt;    /// &amp;lt;param name="y"&amp;gt;modreq&amp;lt;/param&amp;gt;&lt;br /&gt;    void modifiers(const int x, volatile int y) { }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;This feature may be implemented, but only for a small number of variations in the types of method parameters. &amp;nbsp;The problem lies in the placement of the &lt;font class="Apple-style-span" face="'Courier New'"&gt;&lt;a id="h4u6" href="http://msdn.microsoft.com/en-us/library/system.reflection.parameterinfo.getoptionalcustommodifiers.aspx" title="ParameterInfo.GetOptionalCustomModifiers()"&gt;ParameterInfo.GetOptionalCustomModifiers()&lt;/a&gt;&lt;/font&gt;&amp;nbsp;and &lt;font class="Apple-style-span" face="'Courier New'"&gt;&lt;a id="s80p" href="http://msdn.microsoft.com/en-us/library/system.reflection.parameterinfo.getrequiredcustommodifiers.aspx" title="ParameterInfo.GetRequiredCustomModifiers()"&gt;ParameterInfo.GetRequiredCustomModifiers()&lt;/a&gt;&lt;/font&gt;&amp;nbsp;methods. &amp;nbsp;These methods are specific to a parameter, and I believe that they should be generalized and applied to any instance of&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;System.Type&lt;span style="font-family: Verdana"&gt;. &amp;nbsp;For instance, consider the following method.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;pre class="brush: c++"&gt;public ref class C&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    /// &amp;lt;summary/&amp;gt;&lt;br /&gt;    /// &amp;lt;param name="param"&amp;gt;Generic action containing modreq/modopt generic argument.&amp;lt;/param&amp;gt;&lt;br /&gt;    generic &amp;lt;typename T&amp;gt;&lt;br /&gt;    void f(Action&amp;lt;const volatile T&amp;gt;^ param) { }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;The sole parameter&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;param&lt;/font&gt; of function &lt;font class="Apple-style-span" face="'Courier New'"&gt;f&lt;/font&gt; does not have a custom modifier, however the generic method argument T that participates in the definition of the parameter type does. &amp;nbsp;In this case, it doesn't make sense to call &lt;font class="Apple-style-span" face="'Courier New'"&gt;param.GetOptionalCustomModifiers()&lt;/font&gt; since the modifiers apply to T. &amp;nbsp;To get the metadata for T, we need to call &lt;font class="Apple-style-span" face="'Courier New'"&gt;&lt;a id="ww02" href="http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.getgenericarguments.aspx" title="GetGenericArguments()"&gt;GetGenericArguments()&lt;/a&gt;&lt;/font&gt;&amp;nbsp;resulting in a &lt;font class="Apple-style-span" face="'Courier New'"&gt;System.Type&lt;/font&gt; array. &amp;nbsp;But,&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;System.Type&lt;/span&gt;&amp;nbsp;&lt;a id="ux89" href="http://msdn.microsoft.com/en-us/library/system.type_members.aspx" title="does not"&gt;does not&lt;/a&gt; provide a means to get its custom modifiers! &amp;nbsp;A similar problem also exists with array and pointer types as custom modifiers are applied to the element type of these entities. &amp;nbsp;We need to call &lt;font class="Apple-style-span" face="'Courier New'"&gt;&lt;a id="qq3t" href="http://msdn.microsoft.com/en-us/library/system.type.getelementtype.aspx" title="GetElementType()"&gt;GetElementType()&lt;/a&gt;&lt;/font&gt;&amp;nbsp;on the array/pointer type, but are again presented with a&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;System.Type&lt;/span&gt;&amp;nbsp;instance and with no way to get its custom modifiers.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Regarding this issue, I've opened a &lt;a id="low3" href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=503412" title="bug report"&gt;bug report&lt;/a&gt; with Microsoft in hopes that the API flaw will be addressed in a future version of the .NET Framework.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;However, all is not lost. &amp;nbsp;We can still use the&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;ParameterInfo.GetOptionalCustomModifiers()&lt;/span&gt;&amp;nbsp;and&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;ParameterInfo.GetRequiredCustomModifiers()&lt;/span&gt;&amp;nbsp;methods to get custom modifiers for a parameter that is not an array, pointer, or decorated with the by-ref/out attributes (all of these types require us to call&amp;nbsp;&lt;span style="font-family: 'Courier New'"&gt;GetElementType()&lt;/span&gt;&amp;nbsp;to get the type to which the modifier is applied). &amp;nbsp;Also, the parameter can not be dependent on a generic method or type parameter having a custom modifier applied to it. &amp;nbsp;This will at least expose the feature to a small number of methods, but it clearly won't work in the general case. &amp;nbsp;Consequently, I've decided to postpone implementing this feature until I get clearer direction from the community. &amp;nbsp;If you would like to see this feature implement in Jolt.NET, please vote it up on the &lt;a id="t0:9" href="http://jolt.codeplex.com/WorkItem/AdvancedList.aspx" title="Jolt.NET CodePlex"&gt;Jolt.NET CodePlex&lt;/a&gt; web site.&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-7255143156116636721?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Xp32TEE-KDhBC_VxuiidoNdpMnY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Xp32TEE-KDhBC_VxuiidoNdpMnY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Xp32TEE-KDhBC_VxuiidoNdpMnY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Xp32TEE-KDhBC_VxuiidoNdpMnY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=5B6Re3yhaww:iWonPs1dxyU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=5B6Re3yhaww:iWonPs1dxyU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=5B6Re3yhaww:iWonPs1dxyU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=5B6Re3yhaww:iWonPs1dxyU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/5B6Re3yhaww" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/7255143156116636721/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=7255143156116636721" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/7255143156116636721?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/7255143156116636721?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/5B6Re3yhaww/limitations-to-xml-doc-comment-parsing.html" title="Limitations to XML Doc Comment Parsing" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/10/limitations-to-xml-doc-comment-parsing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UMQHs7eip7ImA9WxNXFE4.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-8233035253783411288</id><published>2009-10-01T16:08:00.001-07:00</published><updated>2009-10-01T16:21:21.502-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-01T16:21:21.502-07:00</app:edited><title>Recent Jolt.NET Revisions and Xml Doc Comment Parsing</title><content type="html">I try to make a habit of posting to the development blog each time a significant feature or piece of code gets committed to the source repository. &amp;nbsp;Consequently, I would like to use this post to summarize what has been committed in the past month as several updates have been made. &amp;nbsp;Also, I'll describe some of the work I've been doing on matching XML doc comment elements with their corresponding metadata type from the&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;System.Reflection&lt;/font&gt;&amp;nbsp;namespace.&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;Commit Summary&lt;/u&gt;&lt;/div&gt;&lt;br&gt;&lt;div&gt;Maintenance and refactoring is the main aspect of the Jolt.NET 0.4 release. &amp;nbsp;Prior to this release, I've intentionally delayed many code clean-up tasks as well as performing upgrades of 3rd party dependencies so that I could work on more important features. &amp;nbsp;Now that all those features are complete, I have spent some time to restore the code to its "pristine" state. &amp;nbsp;Here is a summary of the recent updates related to maintenance.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Updated QuickGraph dependency to QuickGraph 3.3.40824&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Removed FSM-&amp;gt;MSAGL conversion code as MSAGL is no longer supported by QuickGraph (superseded by GLEE)&lt;/li&gt;&lt;li&gt;Removed explicit implementation of equality semantics for Transition class as it is now supported natively by QuickGraph's&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;EquatableEdge&lt;/font&gt;&amp;nbsp;type&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Updated RhinoMocks dependency to RhinoMocks 3.6&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Modified relevant unit tests to utilize Act-Arrange-Assert syntax&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Update NUnit dependency to NUnit 2.5.2&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Adopted the use of new constraints to simplify and/or strengthen existing unit tests&lt;/li&gt;&lt;li&gt;Added additional unit tests to verify presence of attributes on types and their members, a task facilitated by the new constraints in NUnit 2.5&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Unit test maintenance&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Fixed many issues that prevented unit tests from being run in an NUnit project (aggregating many test fixtures)&lt;/li&gt;&lt;li&gt;Moved much of the reflection code for accessing types and members by strings into separate classes, improving the readability of some unit tests&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;The following commits introduced new features that were previously planned to be included with the Jolt.NET 0.4 release.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Jolt.Convert&lt;/font&gt;&amp;nbsp;class will now correctly generate the XML doc comments representation of an explicit or implicit operator&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Predefined .NET operators were already supported&lt;/li&gt;&lt;li&gt;Consequently, you can now process XML doc comments with a&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;System.Reflection.MethodInfo&lt;/font&gt;&amp;nbsp;type referring to an operator&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Created the&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Jolt.Testing.Assertions.VisualStudio.XmlAssert&lt;/font&gt;&amp;nbsp;class to integrate the Jolt XML assertions to the Visual Studio test framework&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;u&gt;XML Doc Comment Processing&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;"&lt;a id="uj5l" href="http://msdn.microsoft.com/en-us/library/fsbx0t7x.aspx" title="Processing the XML File (C# Programming Guide)"&gt;Processing the XML File (C# Programming Guide)&lt;/a&gt;" describes the supported XML doc comment markup for various types, methods, parameters, and fields. &amp;nbsp;For a given metadata type instance,&amp;nbsp;&lt;font class="Apple-style-span" face="'Courier New'"&gt;Jolt.Convert&lt;/font&gt;&amp;nbsp;will produce the correct markup, with the exception of the following constructs.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Function pointer parameter (&lt;font class="Apple-style-span" face="'Courier New'"&gt;ELEMENT_TYPE_FNPTR&lt;/font&gt;)&lt;/li&gt;&lt;li&gt;Optional understanding modifier (&lt;font class="Apple-style-span" face="'Courier New'"&gt;ELEMENT_TYPE_CMOD_OPT&lt;/font&gt;)&lt;/li&gt;&lt;li&gt;Required understanding modifier (&lt;font class="Apple-style-span" face="'Courier New'"&gt;ELEMENT_TYPE_CMOD_REQ&lt;/font&gt;)&lt;/li&gt;&lt;li&gt;Pinned field (&lt;font class="Apple-style-span" face="'Courier New'"&gt;ELEMENT_TYPE_PINNED&lt;/font&gt;)&lt;/li&gt;&lt;li&gt;Dimensionless and rank-less array (&lt;font class="Apple-style-span" face="'Courier New'"&gt;ELEMENT_TYPE_GENERICARRAY&lt;/font&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;In order to verify that my implementation is correct, I compare the output of a .NET compiler with the output of the&amp;nbsp;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;Jolt.Convert&lt;/span&gt;&amp;nbsp;class. &amp;nbsp;Since the C# language does not currently support these constructs directly, other means are required for testing the implementation of the&amp;nbsp;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;Jolt.Convert&lt;/span&gt;&amp;nbsp;class, which are demonstrated below.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;To produce XML doc comments with&amp;nbsp;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_FNPTR&lt;/span&gt;, &lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_CMOD_OPT&lt;/span&gt;, and &lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_CMOD_REQ&lt;/span&gt; markup, we may use the the C++/CLI compiler to compile the following class.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;pre class="brush: cpp"&gt;public ref class XmlDocCommentTest&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    typedef int (*function_ptr)(char, int, double);&lt;br /&gt;&lt;br /&gt;    void fnptr(function_ptr f);    // ELEMENT_TYPE_FNPTR&lt;br /&gt;    void mod_opt(const int n);     // ELEMENT_TYPE_CMOD_OPT&lt;br /&gt;    void mod_req(volatile int n);  // ELEMENT_TYPE_CMOD_REQ&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Function pointers are a common construct for C/C++ developers, but understanding why const and volatile translate to optional and required modifiers requires some explanation. &amp;nbsp;Paul DiLascia covers this topic in his article "&lt;a id="ng_w" href="http://msdn.microsoft.com/en-us/magazine/cc163484.aspx" title="C++ At Work: Rationales, Highlights, and a Farewell"&gt;C++ At Work: Rationales, Highlights, and a Farewell&lt;/a&gt;".&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_PINNED&lt;/span&gt;&amp;nbsp;is a bit more tricky since the&amp;nbsp;&lt;a id="i_-x" href="http://msdn.microsoft.com/en-us/library/1dz8byfh.aspx" title="general C++ literature"&gt;general C++ literature&lt;/a&gt;&amp;nbsp;on pinned pointers states that their usage is restricted to non-static local stack variables, which can not be decorated with XML doc comments. &amp;nbsp;However, the&amp;nbsp;&lt;a id="g8n8" href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.aspx" title="System.Runtime.CompilerServices"&gt;&lt;font class="Apple-style-span" face="'Courier New'"&gt;System.Runtime.CompilerServices&lt;/font&gt;&lt;/a&gt; namespace gives some hints on how discover that a field&amp;nbsp;&lt;a id="wmm3" href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.ispinned.aspx" title="is pinned"&gt;is pinned&lt;/a&gt;.&amp;nbsp; Unfortunately I do not know of a way to verify this behavior using a .NET compiler or other tool.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Finally,&amp;nbsp;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_GENERICARRAY&lt;/span&gt; appears to be deprecated as I can not locate any reference to it in modern .NET documentation (apart from the aforementioned document).&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;In the mean time, I plan to implement support for all&amp;nbsp;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_FNPTR&lt;/span&gt;, &lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_CMOD_OPT&lt;/span&gt;, and &lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_CMOD_REQ&lt;/span&gt; in Jolt.NET 0.4. &amp;nbsp;For&amp;nbsp;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;"&gt;ELEMENT_TYPE_PINNED&lt;/span&gt;, I will wait until the feature is highly requested or until I stumble upon a tool that will produce the desired output.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-8233035253783411288?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/i3n-kzaKD4uFfm2bdkLfcM-iRc4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/i3n-kzaKD4uFfm2bdkLfcM-iRc4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/i3n-kzaKD4uFfm2bdkLfcM-iRc4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/i3n-kzaKD4uFfm2bdkLfcM-iRc4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=qtJ2yg22E5o:Aplhhv1EKxk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=qtJ2yg22E5o:Aplhhv1EKxk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=qtJ2yg22E5o:Aplhhv1EKxk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=qtJ2yg22E5o:Aplhhv1EKxk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/qtJ2yg22E5o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/8233035253783411288/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=8233035253783411288" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/8233035253783411288?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/8233035253783411288?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/qtJ2yg22E5o/recent-joltnet-revisions-and-xml-doc_8893.html" title="Recent Jolt.NET Revisions and Xml Doc Comment Parsing" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/10/recent-joltnet-revisions-and-xml-doc_8893.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YHRn4_cSp7ImA9WxNSFk0.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-4865406156891757132</id><published>2009-08-29T21:00:00.001-07:00</published><updated>2009-08-29T21:05:37.049-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-29T21:05:37.049-07:00</app:edited><title>Jolt.NET 0.3 and Future Features</title><content type="html">&lt;p&gt;This past afternoon, I committed source &lt;a href="http://jolt.codeplex.com/SourceControl/changeset/view/26346"&gt;revision #26346&lt;/a&gt;, containing the final feature work for Jolt.NET 0.3.&amp;#160; This release took longer than expected because I added features to the release after thinking it may be too small, and those features ended up taking longer to implement than expected.&amp;#160; In the future, I will try to make the releases more timely, as long releases make the project appear unmaintained.&lt;/p&gt;  &lt;p&gt;Jolt.NET 0.3 contains the following new features:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Support for &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.FSM&amp;amp;referringTitle=Home"&gt;converting a finite state machine&lt;/a&gt; to a GLEE or MSAGL graph &lt;/li&gt;    &lt;li&gt;A set of classes to &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Functional&amp;amp;referringTitle=Home"&gt;manage and create delegates and functors&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Core and NUnit &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Testing"&gt;assertions&lt;/a&gt; for XML data &lt;/li&gt;    &lt;li&gt;Ability to &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Testing.CodeGeneration.Proxy&amp;amp;referringTitle=Home"&gt;generalize the return type&lt;/a&gt; when generating proxy/interface types in the Jolt.Testing library &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Please refer to the &lt;a href="http://jolt.codeplex.com/WorkItem/AdvancedList.aspx"&gt;issue tracker&lt;/a&gt; for all features covered by the release, and to the &lt;a href="http://jolt.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=25207"&gt;release page&lt;/a&gt; for download options.&lt;/p&gt;  &lt;p&gt;Jolt.NET 0.4 will be a short maintenance release, which will involve the upgrade of external dependencies.&amp;#160; The dependency upgrade will allow me to simplify some existing code by utilizing a new external library feature, as well as learn how to use such features so that they may be applied in the future..&amp;#160; Furthermore, there have been many maintenance related tasks I’ve been neglecting, and I feel that now is a good time to address them.&amp;#160; Some new features will be added, but only those were previously identified and not included in a preceding release.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-4865406156891757132?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LDwDb57Or4_ZJwuSrf1Xd34e3Bo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LDwDb57Or4_ZJwuSrf1Xd34e3Bo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LDwDb57Or4_ZJwuSrf1Xd34e3Bo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LDwDb57Or4_ZJwuSrf1Xd34e3Bo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=nvBwBmXT57s:DsHDN3UqY7k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=nvBwBmXT57s:DsHDN3UqY7k:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=nvBwBmXT57s:DsHDN3UqY7k:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=nvBwBmXT57s:DsHDN3UqY7k:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/nvBwBmXT57s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/4865406156891757132/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=4865406156891757132" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/4865406156891757132?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/4865406156891757132?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/nvBwBmXT57s/joltnet-03-and-future-features.html" title="Jolt.NET 0.3 and Future Features" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/08/joltnet-03-and-future-features.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIDQXc6eip7ImA9WxNTE0g.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-3855800883321388765</id><published>2009-08-14T08:31:00.001-07:00</published><updated>2009-08-15T10:16:10.912-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-15T10:16:10.912-07:00</app:edited><title>Error Reporting for Xml Equivalency Assertion</title><content type="html">&lt;p&gt;In my &lt;a href="http://joltdev.blogspot.com/2009/06/xml-equality-and-equivalency.html"&gt;last post&lt;/a&gt;, I sketched out the algorithms dealing with XML equality and equivalency assertions.  During the testing of my implementations, I discovered a fundamental problem with the XML equivalency algorithm that made it a nuisance to use: the reporting of the inequivalent element while ignoring element sequence can potentially be too generic and not very usable.  In this post, I will describe some of the problems I encountered and the currently-implemented remediation.  For conciseness, use of the the term &lt;em&gt;inequivalent&lt;/em&gt; will imply that only element sequence ordering is ignored.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;XML Equivalency Assertion Algorithm&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;When we attempt to determine if a list of nodes is equivalent to another list of nodes, we generally perform a set-equality operation on two list-like data structures, comparing each element in one list is to every element in the other list.  Furthermore, given that the elements are not ordered, we can’t stop searching for an element once we detect the first mismatch since the element may exist further ahead in the list of elements to search.  Reporting the precise element causing the inequivalency thus becomes difficult since we need to store extra information: should we stop the search because the mismatch is indeed the mismatch we are looking for, or should we ignore the mismatch so we can continue searching for the inequivalency in the rest of the tree?&lt;/p&gt;  &lt;p&gt;Here is an algorithm that attempts to address the requirements of the XML equivalency assertion, as noted above.&lt;/p&gt;  &lt;pre class="brush: csharp"&gt;&lt;br /&gt;void AreEquivalent(XElement expected, XElement actual)&lt;br /&gt;{&lt;br /&gt;  HashSet&amp;lt;XElement&amp;gt; expectedElements = new HashSet&amp;lt;XElement&amp;gt;(expected.Elements());&lt;br /&gt;  HashSet&amp;lt;XElement&amp;gt; actualElements = new HashSet&amp;lt;XElement&amp;gt;(actual.Elements());&lt;br /&gt;&lt;br /&gt;  if (expectedElements.Count != actualElements.Count)&lt;br /&gt;  {&lt;br /&gt;    // Report 'actual' as offending element.&lt;br /&gt;    throw new Exception();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  foreach (XElement expectedChild in expectedElements)&lt;br /&gt;  {&lt;br /&gt;    XElement equivalentChild = actualElements.FindFirstOrDefault(e =&amp;gt;&lt;br /&gt;    {&lt;br /&gt;      try { AreEquivalent(expectedChild, e); }&lt;br /&gt;      catch(Exception) { return false; }&lt;br /&gt;      return true;&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    if (equivalentChild == null)&lt;br /&gt;    {&lt;br /&gt;      // Report 'expectedChild' as offending element.&lt;br /&gt;      throw new Exception();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    actualElements.Remove(equivalentChild);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;  &lt;p&gt;This algorithm, hereon mentioned as &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt;, runs in quadratic time (expected for set comparison of two lists), and leverages the optimization that only the first inequivalent element need to be reported.  If all inequivalent elements were to be reported, we would need to implement one of the many &lt;a href="http://useless-factor.blogspot.com/2008/01/matching-diffing-and-merging-xml.html"&gt;tree-diff algorithms&lt;/a&gt;, all of which have greater runtime complexity.&lt;/p&gt; &lt;p&gt;&lt;u&gt;Reporting Offending Elements&lt;/u&gt;&lt;/p&gt; &lt;p&gt;Consider the following XML snippets which are clearly inequivalent due to the presence of an unexpected child element from the root node.&lt;/p&gt;  &lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;!-- Expected XML --&amp;gt;&lt;br /&gt;&amp;lt;parent&amp;gt;&lt;br /&gt;  &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;  &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;  &amp;lt;childNode/&amp;gt;&lt;br /&gt;&amp;lt;/parent&amp;gt;&lt;/pre&gt;  &lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;!-- Actual XML --&amp;gt;&lt;br /&gt;&amp;lt;parent&amp;gt;&lt;br /&gt;  &amp;lt;bogusNode/&amp;gt;&lt;br /&gt;  &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;  &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;&amp;lt;/parent&amp;gt;&lt;/pre&gt; &lt;p&gt;We want to report that &lt;span style="font-family:Courier New;"&gt;bogusNode&lt;/span&gt; is the offending element, but at the same time we want to avoid categorizing the following related XML snippets as invalid.&lt;/p&gt;  &lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;!-- Expected XML --&amp;gt;&lt;br /&gt;&amp;lt;root&amp;gt;&lt;br /&gt;  &amp;lt;parent&amp;gt;&lt;br /&gt;    &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;    &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;    &amp;lt;childNode/&amp;gt;&lt;br /&gt;  &amp;lt;/parent&amp;gt;&lt;br /&gt;  &amp;lt;parent&amp;gt;&lt;br /&gt;    &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;    &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;    &amp;lt;bogusNode/&amp;gt;&lt;br /&gt;  &amp;lt;/parent&amp;gt;&lt;br /&gt;&amp;lt;/root&amp;gt;&lt;/pre&gt;  &lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;!-- Actual XML --&amp;gt;&lt;br /&gt;&amp;lt;root&amp;gt;&lt;br /&gt;  &amp;lt;parent&amp;gt;&lt;br /&gt;    &amp;lt;bogusNode/&amp;gt;&lt;br /&gt;    &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;    &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;  &amp;lt;/parent&amp;gt;&lt;br /&gt;  &amp;lt;parent&amp;gt;&lt;br /&gt;    &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;    &amp;lt;childNode/&amp;gt;&lt;br /&gt;    &amp;lt;descendant xmlns="ns"/&amp;gt;&lt;br /&gt;  &amp;lt;/parent&amp;gt;&lt;br /&gt;&amp;lt;/root&amp;gt;&lt;/pre&gt;  &lt;p&gt;At a first glance, &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt; solves the problem of reporting &lt;span style="font-family:Courier New;"&gt;bogusNode&lt;/span&gt; from the first pair of XML documents.  However, although &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt; detects the offending element, it fails to report this element when the recursive calls unwind back the the original caller.  If you trace &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt; for the examples above, you will notice that it always reports the root element of the XML as the offending element, for any inequivalent pair of XML documents.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Algorithm Improvement&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;The problem with &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt; is if the condition that detects the offending element evaluates to true in one stack frame, it will also evaluate to true again in the preceding stack frame, until the recursive call completely unwinds.  In other words, reporting that &lt;span style="font-family:Courier New;"&gt;bogusNode&lt;/span&gt; is inequivalent also causes its parent to be reported as inequivalent through the same condition – see lines 9, 17, and 24..&lt;/p&gt;  &lt;p&gt;I spent a considerable amount of time modifying &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt; in an attempt to address this problem.  Unfortunately, many of my attempts failed as they either reintroduced the condition issue in another manner, or failed to address the issue of premature search termination.  I ultimately realized that while a single-pass through the XML is desirable, it was simply insufficient for what the problem demanded.&lt;/p&gt;  &lt;p&gt;As you may recall, the &lt;a href="http://joltdev.blogspot.com/2009/06/xml-equality-and-equivalency.html"&gt;algorithm for strict equality&lt;/a&gt; is a linear-time algorithm that positionally compares elements from two documents.  If the elements at a given position are not equal, the algorithm terminates immediately and classifies the documents as not equal.  Ideally, &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt; could behave this way if the element ordering of the two documents were similar.  So, a new solution to the equivalency problem is as follows.&lt;/p&gt;  &lt;ul&gt;  &lt;li&gt;Order the elements of a document such that they match the order of elements in the reference document &lt;strong&gt;as best as possible&lt;/strong&gt;&lt;/li&gt;  &lt;li&gt;Run a the equality algorithm with the reference and transformed documents  &lt;ul&gt;  &lt;li&gt;The algorithm terminates upon detection of the first inequivalent node, or if the two documents are equal&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;What does “as best as possible” mean?  It means that we need &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt; to do some additional work in attempting to detect candidate inequivalent elements during the canonicalization step.  For instance, if the best match for a given element is an inequivalent one that differs only in number of child elements, we would want to reorder this element so that the equality algorithm reports a specific and relevant error: inequivalency due to mismatch of number of child elements, for the specific elements involved.&lt;/p&gt; &lt;p&gt;Here is the algorithm that performs the canonicalization of element order.  It runs in quadratic-time and is invoked recursively prior to calling &lt;span style="font-family:Courier New;"&gt;AreEquvialent&lt;/span&gt;.&lt;/p&gt; &lt;pre class="brush: csharp"&gt;&lt;br /&gt;void NormalizeElementOrder(IEnumerable&amp;lt;XElement&amp;gt; expectedChildren, List&amp;lt;XElement&amp;gt; actualChildren)&lt;br /&gt;{&lt;br /&gt;  int nextUnorderedElementIndex = 0;  &lt;br /&gt;  foreach (XElement expectedChild in expectedChildren)&lt;br /&gt;  {&lt;br /&gt;    int numChildElements = expectedChild.Elements().Count();&lt;br /&gt;&lt;br /&gt;    Predicate&amp;lt;XElement&amp;gt; isEquivalentToExpectedChild = new Predicate&amp;lt;XElement&amp;gt;(e =&amp;gt;&lt;br /&gt; {&lt;br /&gt;   // Similar to AreEquivalent, but without the recursive call to determine child element equivalency.&lt;br /&gt;   try { AreElementsEquivalent(expectedChild, e); }&lt;br /&gt;   catch (Exception) { return false; }&lt;br /&gt;   return true;&lt;br /&gt; });&lt;br /&gt;    Predicate&amp;lt;XElement&amp;gt; isEquivalentToExpectedChild_Strict =&lt;br /&gt;   e =&amp;gt; isEquivalentToExpectedChild(e) &amp;&amp;&lt;br /&gt;           numChildElements == candidateElement.Elements().Count();&lt;br /&gt;&lt;br /&gt;    // Look for the element that best resembles expectedChild considering the configuration&lt;br /&gt;    // the assertion, along with the number of child elements for expectedChild.&lt;br /&gt;    int equivalentChildIndex = actualChildren.FindIndex(nextUnorderedElementIndex, isEquivalentToExpectedChild_Strict);&lt;br /&gt;&lt;br /&gt;    if (equivalentChildIndex &amp;lt; 0)&lt;br /&gt;    {&lt;br /&gt;      // We couldn't find a matching element.  Relax the search criteria&lt;br /&gt;      // by removing the matching child element count constraint and try again.&lt;br /&gt;      equivalentChildIndex = actualChildren.FindIndex(nextUnorderedElementIndex, isEquivalentToExpectedChild);&lt;br /&gt;      if (equivalentChildIndex &amp;lt; 0) { return; }   // No match found, stop normalizing element order.&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    SwapElement(actualChildren, equivalentChildIndex, nextUnorderedElementIndex);&lt;br /&gt;    ++nextUnorderedElementIndex;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Is this the best solution?&amp;#160; I hope so!&amp;#160; Readers, please share your thoughts on this algorithm along with ideas for improving it.&lt;/p&gt;  &lt;p&gt;Now that the equivalency algorithm is implemented and tested, I can resume working on the NUnit and VSTS adapters to the core assertion library.&amp;#160; I am hoping to have the relevant sources sources committed within the next week or so.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-3855800883321388765?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/oZ7DpLGEiH2kIwa_duMtC4QB2v8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oZ7DpLGEiH2kIwa_duMtC4QB2v8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/oZ7DpLGEiH2kIwa_duMtC4QB2v8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oZ7DpLGEiH2kIwa_duMtC4QB2v8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=uxxdfQxBtFE:Uu5QSh4duj0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=uxxdfQxBtFE:Uu5QSh4duj0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=uxxdfQxBtFE:Uu5QSh4duj0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=uxxdfQxBtFE:Uu5QSh4duj0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/uxxdfQxBtFE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/3855800883321388765/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=3855800883321388765" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/3855800883321388765?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/3855800883321388765?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/uxxdfQxBtFE/error-reporting-for-xml-equivalency.html" title="Error Reporting for Xml Equivalency Assertion" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/08/error-reporting-for-xml-equivalency.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QNQX04fCp7ImA9WxJXF0o.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-2056424965142433678</id><published>2009-06-11T18:49:00.001-07:00</published><updated>2009-06-11T18:49:50.334-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-11T18:49:50.334-07:00</app:edited><title>XML Equality and Equivalency</title><content type="html">&lt;p&gt;It’s been a while since I wrote about Jolt.NET, so I thought I’d give a preview of the functionality from the XML assertions I’ve been working on.&amp;#160; I’m currently working on wrapping-up the core assertion functionality, which can ultimately be exposed through test-framework-specific interfaces.&lt;/p&gt;  &lt;p&gt;When I attempt to verify XML in unit tests, I usually am performing one of the following tasks.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Schema validation &lt;/li&gt;    &lt;li&gt;Verifying that a tree contains a particular value in a specific location &lt;/li&gt;    &lt;li&gt;Verifying that a tree contains the same structure and values as another tree&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For the purposes of this discussion, I will focus on the third point as it is trivial to accomplish the first two using .NET XML validation and XPath, respectively.&amp;#160; On a side note, Jolt.NET XML assertions will support all three of these operations.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Strict Equality&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;What does it mean for two XML documents to be equal?&amp;#160; In the strictest sense, we can apply a byte-per-byte comparison of two XML files and determine if all byte pairs match.&amp;#160; Clearly, this doesn’t work in the general case since things like whitespace, character encoding, and attribute ordering, will all impede the success of the equality algorithm.&amp;#160; All of these items can vary greatly in an XML document and still not change the semantics or structure of the XML.&lt;/p&gt;  &lt;p&gt;In order for the algorithm to work in the general case, it must treat XML entities (elements, attributes, etc…) as single units and define equality semantics for those units.&amp;#160; Furthermore, XML parser support can eliminate the need for dealing with whitespace, processing instruction elements, comments, and other entities that do not affect the semantics of the XML document.&lt;/p&gt;  &lt;p&gt;That said, here is a recursive definition that determines if two XML elements are considered to be equal by value (XML document equality is achieved by comparing root elements for equality).&amp;#160; The algorithm currently used by Jolt.NET XML assertions is based on this definition, and relies on the parsing provided by XmlReader to simplify the implementation.&lt;/p&gt;  &lt;p&gt;Elements &lt;font face="Courier New"&gt;E&lt;/font&gt; and &lt;font face="Courier New"&gt;F&lt;/font&gt; are equal if and only if:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The namespace of &lt;font face="Courier New"&gt;E&lt;/font&gt; equals the namespace of &lt;font face="Courier New"&gt;F&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;The name of &lt;font face="Courier New"&gt;E&lt;/font&gt; equals the name of &lt;font face="Courier New"&gt;F&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;The text node values contained in &lt;font face="Courier New"&gt;E&lt;/font&gt; are equal to the text node values contained in &lt;font face="Courier New"&gt;F&lt;/font&gt;, and must be in the same order&lt;/li&gt;    &lt;li&gt;The set of attributes contained in &lt;font face="Courier New"&gt;E&lt;/font&gt; equals the set of attributes contained in &lt;font face="Courier New"&gt;F&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;The number of child elements of &lt;font face="Courier New"&gt;E&lt;/font&gt; equals the number of child elements of &lt;font face="Courier New"&gt;F&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;For each child element pair (&lt;font face="Courier New"&gt;E.child[i]&lt;/font&gt;, &lt;font face="Courier New"&gt;F.child[i]&lt;/font&gt;), &lt;font face="Courier New"&gt;E.child[i]&lt;/font&gt; is equal to &lt;font face="Courier New"&gt;F.child[i]&lt;/font&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Attributes &lt;font face="Courier New"&gt;A&lt;/font&gt; and &lt;font face="Courier New"&gt;B&lt;/font&gt; are equal if and only if:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The namespace of &lt;font face="Courier New"&gt;A&lt;/font&gt; equals the namespace of &lt;font face="Courier New"&gt;B&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;The name of &lt;font face="Courier New"&gt;A&lt;/font&gt; equals the name of &lt;font face="Courier New"&gt;B&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;The value of &lt;font face="Courier New"&gt;A&lt;/font&gt; equals the value of &lt;font face="Courier New"&gt;B&lt;/font&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You will notice that this algorithm does not discriminate on the position of an element’s attribute.&amp;#160; All that is required is that the attribute in question exists in the set of attributes of the compared element, as defined by the rules for attribute equality.&amp;#160; On the contrary, child element ordering is considered as part of the evaluation since an XML schema [element-sequence] generally implies order.&lt;/p&gt;  &lt;p&gt;Sometimes, constraints such as namespaces and element ordering pose too much of a restriction and make XML comparison tedious.&amp;#160; Jolt.NET XML assertions aim to address this issue by allowing the option to relax some of the constraints of the equality algorithm.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Equivalency – Relaxed Equality&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;In Jolt.NET, equivalency between two XML elements is defined by choosing to relax any combination of a set of constraints.&amp;#160; The following directives are currently supported.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;For element comparisons, ignore element namespaces &lt;/li&gt;    &lt;li&gt;For element comparisons, ignore element values (child text nodes)&lt;/li&gt;    &lt;li&gt;For element comparisons, ignore ordering of child elements&lt;/li&gt;    &lt;li&gt;For element comparisons, ignore their attributes&lt;/li&gt;    &lt;li&gt;For attribute comparisons, ignore attribute namespaces&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The interesting algorithm from the above list of directives is the one that processes child elements, yet ignores their ordering.&amp;#160; Here is another recursive definition that determines if two sets of child elements are equivalent.&amp;#160; The algorithm currently used by Jolt.NET XML assertions is based on this definition.&lt;/p&gt;  &lt;p&gt;Assume that the method &lt;font face="Courier New"&gt;bool AreEquivalent(element, element)&lt;/font&gt; exists and, denotes if two given elements are equivalent according to the user-specified equivalency directives and constraints, listed above.&amp;#160; Then, two sets of child elements, &lt;font face="Courier New"&gt;C&lt;/font&gt; and &lt;font face="Courier New"&gt;D&lt;/font&gt;, are equivalent if and only if:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The number of elements in &lt;font face="Courier New"&gt;C&lt;/font&gt; equals the number of elements in &lt;font face="Courier New"&gt;D&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;For each child element C[i], there exists a unique child element &lt;font face="Courier New"&gt;D[j]&lt;/font&gt; such that &lt;font face="Courier New"&gt;AreEquivialent(C[i], D[j]) == true&lt;/font&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Note that the term “unique” is important – it denotes that any given element can only be matched once for the entire operation. The use of indexes &lt;font face="Courier New"&gt;i&lt;/font&gt; and &lt;font face="Courier New"&gt;j&lt;/font&gt; shows that the ordering of elements is not important and that a search is required to locate the desired element.&lt;/p&gt;  &lt;p&gt;So there you have it – the definitions of equality and equivalency for XML.&amp;#160; Do let me know if you think I’ve missed something in my definitions!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-2056424965142433678?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/R9fPU9F5amr4aVyuZo3MjBxqzEM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/R9fPU9F5amr4aVyuZo3MjBxqzEM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/R9fPU9F5amr4aVyuZo3MjBxqzEM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/R9fPU9F5amr4aVyuZo3MjBxqzEM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=6--GcSuUxIw:2xZE7OXFdfM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=6--GcSuUxIw:2xZE7OXFdfM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=6--GcSuUxIw:2xZE7OXFdfM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=6--GcSuUxIw:2xZE7OXFdfM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/6--GcSuUxIw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/2056424965142433678/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=2056424965142433678" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/2056424965142433678?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/2056424965142433678?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/6--GcSuUxIw/xml-equality-and-equivalency.html" title="XML Equality and Equivalency" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/06/xml-equality-and-equivalency.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IARH89eSp7ImA9WxJREEg.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-8205288919892735408</id><published>2009-05-11T08:00:00.000-07:00</published><updated>2009-05-11T08:25:45.161-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-11T08:25:45.161-07:00</app:edited><title>Jolt.NET Feature Triage</title><content type="html">You may have noticed through the &lt;a href="http://jolt.codeplex.com/Project/ProjectRss.aspx?ProjectRSSFeed=codeplex://workitem/jolt"&gt;feature RSS feed&lt;/a&gt; that I've been busy opening/closing items and shuffling things around.  I've postponed work on some documentation tasks that didn't make much sense for a project of one developer.  Also, I decided that I &lt;a href="http://jolt.codeplex.com/WorkItem/View.aspx?WorkItemId=4024"&gt;won't implement&lt;/a&gt; the Tuple library as the upcoming release of the .NET Framework 4.0 will contain an implementation similar to what I had planned.  .NET 4.0 is currently available in beta/CTP for &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=922B4655-93D0-4476-BDA4-94CF5F8D4814&amp;amp;displaylang=en"&gt;download&lt;/a&gt;.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The triage slashed the number of items that I wanted to complete for Jolt.NET 0.3, and that prompted me to think about including another feature in the release.  When I first started work on Jolt.NET, I wanted to include a test facility to make assertions on XML data structures.  After releasing Jolt.NET 0.1, I decided &lt;a href="http://joltdev.blogspot.com/2008/12/joltnet-intial-release-and-future.html"&gt;not to implement&lt;/a&gt; this feature as it would be available in NUnit 3.0.  However, I think this decision was premature as not all testing frameworks will support this feature.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So over the next few days, I will be drafting an implementation and feature set for extending a test framework to support assertions on XML data.  I suspect that I will need some adapter classes to expose the feature in various test frameworks, and at this time, I'm not sure how many of these frameworks to support.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-8205288919892735408?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mHXCOGFCHQVhF36USDD2ev5k-9o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mHXCOGFCHQVhF36USDD2ev5k-9o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mHXCOGFCHQVhF36USDD2ev5k-9o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mHXCOGFCHQVhF36USDD2ev5k-9o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Dz106la-KpM:eedaK0ZGM6k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Dz106la-KpM:eedaK0ZGM6k:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=Dz106la-KpM:eedaK0ZGM6k:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Dz106la-KpM:eedaK0ZGM6k:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/Dz106la-KpM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/8205288919892735408/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=8205288919892735408" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/8205288919892735408?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/8205288919892735408?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/Dz106la-KpM/joltnet-feature-triage.html" title="Jolt.NET Feature Triage" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/05/joltnet-feature-triage.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QHRnkyeSp7ImA9WxJSGUU.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-3027232169882985962</id><published>2009-05-10T11:46:00.001-07:00</published><updated>2009-05-10T11:48:57.791-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-10T11:48:57.791-07:00</app:edited><title>Static Idempotent Functors</title><content type="html">&lt;p&gt;The &lt;a href="http://jolt.codeplex.com/WorkItem/View.aspx?WorkItemId=3628"&gt;task&lt;/a&gt; of replacing inline anonymous methods with a generic functor from the &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Functional&amp;amp;referringTitle=Home"&gt;Jolt.Functional&lt;/a&gt; library brought forth some interesting issues, all of which have been addressed as of &lt;a href="http://jolt.codeplex.com/SourceControl/changeset/view/19483"&gt;revision #19483&lt;/a&gt;.&amp;#160; The main topic that I will discuss in this post deals with the implementation and usage of the &lt;font face="Courier New"&gt;Functor.Idempotency&lt;/font&gt; and &lt;font face="Courier New"&gt;Functor.TrueForAll&lt;/font&gt; generic factory methods.&lt;/p&gt;  &lt;p&gt;The &lt;font face="Courier New"&gt;TrueForAll&lt;/font&gt; factory method creates a delegate that returns &lt;font face="Courier New"&gt;true&lt;/font&gt; for any input, and thus it is natural to implement this method in terms of the &lt;font face="Courier New"&gt;Functor.Idempotency&lt;/font&gt; method since &lt;font face="Courier New"&gt;TrueForAll&lt;/font&gt; is a Boolean idempotent predicate.&amp;#160; My main use of &lt;font face="Courier New"&gt;TrueForAll&lt;/font&gt; in Jolt.NET was in testing the &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.FSM&amp;amp;referringTitle=Home#usage-examples-graphML-serialization"&gt;serialization of finite automata to GraphML&lt;/a&gt;.&amp;#160; If you’ve used this library, you may recall that there are &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.FSM&amp;amp;referringTitle=Home#design-scope-serialization"&gt;limitations&lt;/a&gt; when serializing of a &lt;font face="Courier New"&gt;TransitionPredicate.&lt;/font&gt;&amp;#160; Specifically, the predicate must refer to a static method.&amp;#160; So, is it possible to implement a generic idempotent method that is static?&amp;#160; Let’s take a look at the function signature that we need to satisfy, along with the current implementation.&lt;/p&gt;  &lt;pre class="brush: csharp"&gt;using System;&lt;br /&gt; &lt;br /&gt;// One-arg idempotent method; overloads exist for zero through four args.&lt;br /&gt;static Func&amp;lt;T, TResult&amp;gt; Idempotency&amp;lt;T, TResult&amp;gt;(TResult constant)&lt;br /&gt;{&lt;br /&gt;  return arg =&amp;gt; constant;&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;In this example, the method that ultimately implements the inline expression can not be static since it uses a variable that is not local to the expression (see “&lt;a href="http://joltdev.blogspot.com/2009/04/anonymous-methods-and-jolt-functors.html"&gt;Anonymous Methods and Jolt Functors: Behind the Scenes&lt;/a&gt;” for more information).&amp;#160; Consequently, the resulting delegate refers to a non-static method.&amp;#160; If the hidden class that implements the expression were static, then we could only ever have one idempotent delegate per unique specialization. per app-domain, as demonstrated in the following example.&lt;/p&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;using System;&lt;br /&gt; &lt;br /&gt;static class IdemptotencyWrapper&amp;lt;TConstant&amp;gt;&lt;br /&gt;{&lt;br /&gt;  static TConstant constant;&lt;br /&gt;  static TConstant Idempotency&amp;lt;T&amp;gt;(T arg)&lt;br /&gt;  {&lt;br /&gt;    return constant;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;static Func&amp;lt;T, TResult&amp;gt; Idempotency&amp;lt;T, TResult&amp;gt;(TResult constant)&lt;br /&gt;{&lt;br /&gt;  IdempotencyWrapper&amp;lt;TResult&amp;gt;.constant = constant;&lt;br /&gt;  return IdempotencyWrapper&amp;lt;TResult&amp;gt;.Idempotency&amp;lt;T&gt;;&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;void UseFunctors()&lt;br /&gt;{&lt;br /&gt; Func&amp;lt;int, bool&amp;gt; falseForAll = Idempotency&amp;lt;int&amp;gt;(false);&lt;br /&gt; Func&amp;lt;int, bool&amp;gt; trueForAll = Idempotency&amp;lt;int&amp;gt;(true);  // Oops! Changed the behavior of falseForAll.&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Another novel attempt at solving this problem is to use an expression tree to force the user-provided constant to be local to the expression.&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using System;&lt;br /&gt; &lt;br /&gt;static Func&amp;lt;T, TResult&amp;gt; Idempotency&amp;lt;T, TResult&amp;gt;(TResult constant)&lt;br /&gt;{&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;T, TResult&amp;gt;&amp;gt; expression = Expression.Lambda(&lt;br /&gt;    Expression.Constant(constant, typeof(TResult)),&lt;br /&gt;    new[] { Expression.Parameter(typeof(T), arg) });&lt;br /&gt;  return expression.Compile();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This solution &lt;em&gt;looks&lt;/em&gt; good, has some performance deficiencies we can live with, and may even provide the static method that we need.&amp;#160; However, the method that is produced is compiled and created at runtime.&amp;#160; In other words, it doesn’t exist in the assembly and thus not feasible for textual serialization.&lt;/p&gt;&lt;p&gt;I’m also uncertain on whether this method is truly static.&amp;#160; The &lt;font face="Courier New"&gt;MethodInfo&lt;/font&gt; object representing the delegate’s method states that &lt;font face="Courier New"&gt;IsStatic&lt;/font&gt; is &lt;font face="Courier New"&gt;true&lt;/font&gt;, but the delegate’s &lt;font face="Courier New"&gt;Target&lt;/font&gt; property gives a non-null value.&amp;#160; Very strange.&lt;/p&gt;&lt;p&gt;If we want to persist the method that is represented by the expression, we can utilize the Reflection.Emit API and create an assembly that contains the desired method.&amp;#160; The performance deficiency is even greater with this solution and is overkill for the general usage of the &lt;font face="Courier New"&gt;Idempotency&lt;/font&gt; method.&amp;#160; While the serialization problem is addressed, the deserialization problem is not; this generated assembly is not distributed with the library and thus the referenced methods may not exist in deserialization environment.&lt;/p&gt;&lt;p&gt;In conclusion, I could not conceive of a way to modify the &lt;font face="Courier New"&gt;Idempotency&lt;/font&gt; method implementation to meet my criteria, so I decided to keep it as is.&amp;#160; The implementations of &lt;font face="Courier New"&gt;TrueForAll&lt;/font&gt; and &lt;font face="Courier New"&gt;FalseForAll&lt;/font&gt; were modified to return constants local to the expressions, thus making the resulting delegate refer to a static method.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-3027232169882985962?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jajhs2sxorpmNVC9OrEzn27e9xQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jajhs2sxorpmNVC9OrEzn27e9xQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jajhs2sxorpmNVC9OrEzn27e9xQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jajhs2sxorpmNVC9OrEzn27e9xQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=AIiONWoKdvU:IOAC1Q57etc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=AIiONWoKdvU:IOAC1Q57etc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=AIiONWoKdvU:IOAC1Q57etc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=AIiONWoKdvU:IOAC1Q57etc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/AIiONWoKdvU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/3027232169882985962/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=3027232169882985962" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/3027232169882985962?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/3027232169882985962?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/AIiONWoKdvU/static-idempotent-functors.html" title="Static Idempotent Functors" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/05/static-idempotent-functors.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUEQ3k4fip7ImA9WxJSF0k.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-4507113019379700794</id><published>2009-05-07T18:41:00.001-07:00</published><updated>2009-05-07T18:46:42.736-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-07T18:46:42.736-07:00</app:edited><title>Adaptors For Delegate Types</title><content type="html">&lt;p&gt;Recently, I’ve been working on creating adaptors for delegates of equivalent types.&amp;#160; Given the generic types &lt;font face="Courier New"&gt;Predicate&amp;lt;T&amp;gt;&lt;/font&gt; and &lt;font face="Courier New"&gt;EventHandler&amp;lt;TEventArgs&amp;gt;&lt;/font&gt;, I would like to create a function that transforms instances of these types into &lt;font face="Courier New"&gt;Func&amp;lt;T, bool&amp;gt;&lt;/font&gt; and &lt;font face="Courier New"&gt;Action&amp;lt;object, TEventArgs&amp;gt;&lt;/font&gt; respectively, and vice-versa.&amp;#160; This is a fairly straight-forward task to accomplish, but implementing a correct solution depends on what your expectations are with regards to what the resulting delegate references.&lt;/p&gt;  &lt;p&gt;My goal is to create a new adaptor delegate that refers to the same method that is referred to by the adaptee.&amp;#160; When implementing the adaptor function for the &lt;font face="Courier New"&gt;Predicate&amp;lt;T&amp;gt;&lt;/font&gt;/&lt;font face="Courier New"&gt;Func&amp;lt;T, bool&amp;gt;&lt;/font&gt; case, I implemented the incorrect solution twice.&amp;#160; On the second attempt, I also implemented the incorrect test code, which was very negligent on my part.&amp;#160; It was only until other unrelated tests start failing, that I noticed my error: I had changed the semantics of the implementation and consequently the expectations of the unit tests.&lt;/p&gt;  &lt;p&gt;Let’s look at three ways to implement a function that creates an adaptor delegate for &lt;font face="Courier New"&gt;Predicate&amp;lt;T&amp;gt;&lt;/font&gt;.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Option 1 : Lambda Expressions&lt;/u&gt;&lt;/p&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;using System;&lt;br /&gt;&lt;br /&gt;Func&amp;lt;T, bool&amp;gt; CreateFunc&amp;lt;T&amp;gt;(Predicate&amp;lt;T&amp;gt; predicate)&lt;br /&gt;{&lt;br /&gt;  return arg =&amp;gt; predicate(arg);&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;This solution uses a lambda expression to create a new delegate that forwards its call to the adaptee.&amp;#160; The forwarding operation is implemented by the compiler as a new method on a compiler-generated type.&amp;#160; Clearly, this is does not achieve my goal since the method referred to by the adaptor is different from that referred to by the adaptee.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Option 2 : Delegate Constructor&lt;/u&gt;&amp;#160;&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using System;&lt;br /&gt;&lt;br /&gt;Func&amp;lt;T, bool&amp;gt; CreateFunc&amp;lt;T&amp;gt;(Predicate&amp;lt;T&amp;gt; predicate)&lt;br /&gt;{&lt;br /&gt;  return new Func&amp;lt;T, bool&amp;gt;(predicate);&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;This solution initializes an instance of the adaptor delegate with the adaptee instance.&amp;#160; It looks like a copy constructor has been invoked, as the constructor accepts anything that implements the delegate’s signature.&amp;#160; However, don’t be deceived by the copy-constructor-like syntax of this operation.&amp;#160; The constructor has in fact added the adaptee to the adaptor’s invocation list.&amp;#160; Consequently, the method referred to by the adaptor is the Invoke() method of the adaptee.&amp;#160; If the constructor parameter were a method, then the resulting adaptor delegate would refer directly to the given method.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Option 3 : Delegate Factory Method&lt;/u&gt;&lt;/p&gt;&lt;pre class="brush: csharp"&gt;using System;&lt;br /&gt;&lt;br /&gt;Func&amp;lt;T, bool&amp;gt; CreateFunc&amp;lt;T&amp;gt;(Predicate&amp;lt;T&amp;gt; predicate)&lt;br /&gt;{&lt;br /&gt;  return Delegate.CreateDelegate(typeof(Func&amp;lt;T, bool&amp;gt;), predicate.Target, predicate.Method) as Func&amp;lt;T, bool&amp;gt;;&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;This solution utilizes a bit of reflection and a static factory method on the delegate class to construct the adaptor.&amp;#160; Notice that the factory method accepts a &lt;font face="Courier New"&gt;MethodInfo&lt;/font&gt; object, denoting the method that the resulting delegate will &lt;em&gt;directly&lt;/em&gt; invoke.&amp;#160; Alas, we have arrived at the solution that implements my expectations.&amp;#160; Even though the adaptor and adaptee delegates are of different types, they both internally refer to the same method.&lt;/p&gt;&lt;p&gt;There is one gotcha that you should be aware of – this may be a bug with in the .NET Framework, or misstated information in the documentation.&amp;#160; If you refer to the &lt;a href="http://msdn.microsoft.com/en-us/library/53cz7sc6.aspx"&gt;documentation&lt;/a&gt; on the &lt;font face="Courier New"&gt;Delegate.CreateDelegate(Type, MethodInfo)&lt;/font&gt; method, you will notice that the method supports both static and instance methods for binding (.NET 2.0 and onwards).&amp;#160; However, disassembling the method in question shows that this is not the case; this overload only functions with static methods, always passing a null reference as the target object of the new delegate.&amp;#160; In my example above, I use another overload that accepts the target parameter to assure that both static and instance methods are adaptable.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-4507113019379700794?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bhSShgnesbcFy_ggo7hgN1N0lls/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bhSShgnesbcFy_ggo7hgN1N0lls/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bhSShgnesbcFy_ggo7hgN1N0lls/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bhSShgnesbcFy_ggo7hgN1N0lls/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=pS6qk9nRYBE:cVkL-gePxw4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=pS6qk9nRYBE:cVkL-gePxw4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=pS6qk9nRYBE:cVkL-gePxw4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=pS6qk9nRYBE:cVkL-gePxw4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/pS6qk9nRYBE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/4507113019379700794/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=4507113019379700794" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/4507113019379700794?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/4507113019379700794?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/pS6qk9nRYBE/adaptors-for-delegate-types.html" title="Adaptors For Delegate Types" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/05/adaptors-for-delegate-types.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQCRHY-fCp7ImA9WxJSFU0.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-4662446353865037666</id><published>2009-05-04T22:44:00.001-07:00</published><updated>2009-05-04T22:46:05.854-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-04T22:46:05.854-07:00</app:edited><title>Jolt.NET Functor Composition</title><content type="html">&lt;p&gt;I recently completed the implementation of the generic &lt;font face="Courier New"&gt;Compose&lt;/font&gt; class, allowing a caller to build composite functors with up to seven parameters.&amp;#160; In this post, I will discuss the implementation and a minor coding nuisance that I encountered while writing the code.&amp;#160; But first, here is a quick recap the features that were committed since my last post.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font face="Courier New"&gt;Jolt.Functional&lt;/font&gt; functor creation and manipulation library (see &lt;a href="http://joltdev.blogspot.com/2009/03/joltnet-restructuring-and-future.html"&gt;this post&lt;/a&gt;, and &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Functional&amp;amp;referringTitle=Home"&gt;the docs&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;Ability to override return type in &lt;font face="Courier New"&gt;Jolt.Testing.ProxyTypeBuilder&lt;/font&gt; (see &lt;a href="http://joltdev.blogspot.com/2009/02/proxytypebuilder-usability-issue.html"&gt;this post&lt;/a&gt;, and &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Testing.CodeGeneration.Proxy&amp;amp;referringTitle=Home"&gt;the docs&lt;/a&gt;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;u&gt;&lt;font face="Courier New"&gt;Compose&lt;/font&gt; Implementation&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;The &lt;font face="Courier New"&gt;Compose&lt;/font&gt; class is implemented as a collection of generic static functions: &lt;font face="Courier New"&gt;First&lt;/font&gt;, &lt;font face="Courier New"&gt;Second&lt;/font&gt;, &lt;font face="Courier New"&gt;Third&lt;/font&gt; and &lt;font face="Courier New"&gt;Fourth&lt;/font&gt;.&amp;#160; Each of these functions binds the execution of a delegate to an argument of another delegate, the position of the argument being denoted by the function’s name. A composite delegate is represented as a new delegate, and its generic implementation takes care of binding arguments and calling the composed delegates at the right time.&amp;#160; Functor composition is very similar to argument binding, except that the bound arguments are now delegates instead of constant values.&lt;/p&gt;  &lt;p&gt;The rules and supported scenarios for creating a composite are straightforward:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You can bind any &lt;font face="Courier New"&gt;System.Func&lt;/font&gt; functor &lt;strong&gt;F&lt;/strong&gt; to an argument &lt;strong&gt;A&lt;/strong&gt; of any &lt;font face="Courier New"&gt;System.Action&lt;/font&gt; or &lt;font face="Courier New"&gt;System.Func&lt;/font&gt; delegate so long as the return type of &lt;strong&gt;F&lt;/strong&gt; matches the type of &lt;strong&gt;A&lt;/strong&gt;. &lt;/li&gt;    &lt;li&gt;Only one functor can be bound per &lt;font face="Courier New"&gt;Compose&lt;/font&gt; method call. &lt;/li&gt;    &lt;li&gt;Bound functors are executed when the resulting composite is executed, in LIFO order.      &lt;ul&gt;       &lt;li&gt;E.g. Given a binary functor &lt;strong&gt;F&lt;/strong&gt;, nullary functors &lt;strong&gt;G&lt;/strong&gt; and &lt;strong&gt;H&lt;/strong&gt;, and the composite &lt;font face="Courier New"&gt;c = Compose.First(Compose.First(&lt;strong&gt;F&lt;/strong&gt;, &lt;strong&gt;G&lt;/strong&gt;), &lt;strong&gt;H&lt;/strong&gt;)&lt;/font&gt;, executing &lt;font face="Courier New"&gt;c()&lt;/font&gt; results in the execution of &lt;strong&gt;H&lt;/strong&gt; first, followed by &lt;strong&gt;G&lt;/strong&gt; and &lt;strong&gt;F&lt;/strong&gt;. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Creating a composite yielding more than four arguments results in a &lt;font face="Courier New"&gt;Jolt.Functional.Action&lt;/font&gt; or &lt;font face="Courier New"&gt;Jolt.Functional.Func&lt;/font&gt; delegate, each of which support five through seven arguments. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;When writing the methods of &lt;font face="Courier New"&gt;Compose&lt;/font&gt;, I was primarily concerned with enforcing the rules from the first bulleted item above at compile-time.&amp;#160; Doing so would ensure that the creation of the composite is as fast as possible since the code would not need to perform checks for possible user errors.&amp;#160; Unfortunately, taking this approach meant that I would need to declare every possible permutation of binding a 1-4 argument delegate with a 0-4 argument functor.&amp;#160; There are a total of &lt;strong&gt;100&lt;/strong&gt; of such combinations, and the only difference between any two given functions is generally the number of delegate arguments and the position at which the binding occurs.&lt;/p&gt;  &lt;p&gt;To the best of my knowledge, there is no way to use generics to reduce the number of functions that are needed to implement all of the desired combinations.&amp;#160; C# &lt;a href="http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx#csharp_generics_topic4"&gt;does not allow&lt;/a&gt; a generic parameter to be constrained to a &lt;font face="Courier New"&gt;System.Delegate&lt;/font&gt; type, and if it were possible, there is still no facility to constrain a delegate to one with a given number of arguments.&amp;#160; For this situation, a C++-like &lt;a href="http://en.wikipedia.org/wiki/Variadic_function#Variadic_functions_in_C.2C_Objective-C.2C_C.2B.2B.2C_and_D"&gt;variadic template argument&lt;/a&gt; or &lt;a href="http://www.ddj.com/cpp/184403813"&gt;typelist&lt;/a&gt; feature is very desirable as it will eliminate the method overloads enabling composition of functors with varying arguments.&amp;#160; To illustrate, one could reduce the number of &lt;font face="Courier New"&gt;First&lt;/font&gt; method overloads from 40 to 8 using the following variadic generic argument pseudocode.&lt;/p&gt;  &lt;pre class="brush: csharp"&gt;public static class Compose&lt;br /&gt;{&lt;br /&gt;  public Func&amp;lt;params Args, TResult&amp;gt;&lt;br /&gt;    First&amp;lt;T, TResult, params Args&amp;gt;(Func&amp;lt;T, TResult&amp;gt; function, Func&amp;lt;params Args, T&amp;gt; innerFunction);&lt;br /&gt;  public Func&amp;lt;params Args, TResult&amp;gt;&lt;br /&gt;    First&amp;lt;T1, T2, TResult, params Args&amp;gt;(Func&amp;lt;T1, T2, TResult&amp;gt; function, Func&amp;lt;params Args, T1&amp;gt; innerFunction);&lt;br /&gt;  public Func&amp;lt;params Args, TResult&amp;gt;&lt;br /&gt;    First&amp;lt;T1, T2, T3, TResult, params Args&amp;gt;(Func&amp;lt;T1, T2, T3, TResult&amp;gt; function, Func&amp;lt;params Args, T1&amp;gt; innerFunction);&lt;br /&gt;  public Func&amp;lt;params Args, TResult&amp;gt;&lt;br /&gt;    First&amp;lt;T1, T2, T3, T4, TResult, params Args&amp;gt;(Func&amp;lt;T1, T2, T3, T4, TResult&amp;gt; function, Func&amp;lt;params Args, T1&amp;gt; innerFunction);&lt;br /&gt;&lt;br /&gt;  public Action&amp;lt;params Args&amp;gt;&lt;br /&gt;    First&amp;lt;T, params Args&amp;gt;(Action&amp;lt;T&amp;gt; function, Func&amp;lt;params Args, T&amp;gt; innerFunction);&lt;br /&gt;  public Action&amp;lt;params Args&amp;gt;&lt;br /&gt;    First&amp;lt;T1, T2, params Args&amp;gt;(Action&amp;lt;T1, T2&amp;gt; function, Func&amp;lt;params Args, T1&amp;gt; innerFunction);&lt;br /&gt;  public Action&amp;lt;params Args&amp;gt;&lt;br /&gt;    First&amp;lt;T1, T2, T3, params Args&amp;gt;(Action&amp;lt;T1, T2, T3&amp;gt; function, Func&amp;lt;params Args, T1&amp;gt; innerFunction);&lt;br /&gt;  public Action&amp;lt;params Args&amp;gt;&lt;br /&gt;    First&amp;lt;T1, T2, T3, T4, params Args&amp;gt;(Action&amp;lt;T1, T2, T3, T4&amp;gt; function, Func&amp;lt;params Args, T1&amp;gt; innerFunction);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;An alternate implementation technique is to utilize reflection to compose abstract &lt;font face="Courier New"&gt;System.Delegate&lt;/font&gt; instances.&amp;#160; As mentioned earlier, this solution requires additional code to guard against user errors.&amp;#160; It would also rely heavily on reflection to determine the type of and create an instance of the resulting delegate.&amp;#160; The implementation will not perform as well as the many-overloads solution, but has the benefit of producing far less code to maintain.&amp;#160; It also removes the restriction of delegate types that are usable with the library (&lt;font face="Courier New"&gt;System.Action&lt;/font&gt; and &lt;font face="Courier New"&gt;System.Func&lt;/font&gt;), even though this isn’t a &lt;a href="http://blogs.msdn.com/brada/archive/2009/01/26/framework-design-guidelines-avoiding-custom-delegates.aspx"&gt;bad restriction&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In the end, I chose to avoid the reflection-based approach favoring runtime speed and a strongly-typed interface over smaller code quantity.&amp;#160; The implementations of the &lt;font face="Courier New"&gt;Compose&lt;/font&gt; methods and their tests are trivial, and if I had to write such a class again, I would likely implement a code generator to emit all of the desired permutations.&amp;#160; Implementing the code generator may not be such a trivial task, but it will likely take far less time than copying and tweaking code, and making sure that the XML doc comments for the new code is correctly specified.&lt;/p&gt;&lt;p&gt;Finally, I should note that the reflection-based approach has the merit of enabling composition/binding support for abstract &lt;font face="Courier New"&gt;System.Delegate&lt;/font&gt; instances.&amp;#160; We can utilize a method similar to the following to convert a &lt;font face="Courier New"&gt;System.Delegate&lt;/font&gt; to its equivalent &lt;font face="Courier New"&gt;System.Action&lt;/font&gt; or &lt;font face="Courier New"&gt;System.Func&lt;/font&gt; counterpart.&amp;#160; The resulting delegate may then be used with the &lt;font face="Courier New"&gt;Jolt.Functional&lt;/font&gt; classes.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;public static class Convert&lt;br /&gt;{&lt;br /&gt;  public static Action ToAction(Delegate function)&lt;br /&gt;  {&lt;br /&gt;    // TODO: validate input and cast.&lt;br /&gt;    return Delegate.CreateDelegate(typeof(Action), function.Method) as Action;&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-4662446353865037666?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/8HJk3voTwfdufyGkm1rTxIahYcI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8HJk3voTwfdufyGkm1rTxIahYcI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/8HJk3voTwfdufyGkm1rTxIahYcI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8HJk3voTwfdufyGkm1rTxIahYcI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=-XO1GVGOxMQ:hzxX_O_Z7vE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=-XO1GVGOxMQ:hzxX_O_Z7vE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=-XO1GVGOxMQ:hzxX_O_Z7vE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=-XO1GVGOxMQ:hzxX_O_Z7vE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/-XO1GVGOxMQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/4662446353865037666/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=4662446353865037666" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/4662446353865037666?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/4662446353865037666?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/-XO1GVGOxMQ/joltnet-functor-composition.html" title="Jolt.NET Functor Composition" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/05/joltnet-functor-composition.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYBQHw_eip7ImA9WxJTE0k.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-470711060375640446</id><published>2009-04-21T09:00:00.001-07:00</published><updated>2009-04-21T11:55:51.242-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-21T11:55:51.242-07:00</app:edited><title>Anonymous Methods and Jolt Functors: Behind the Scenes</title><content type="html">&lt;p&gt;Good day all!  I haven’t written a meaningful article for some time now as I’ve been fairly occupied with work tasks during the past few weeks.  I’ve been dabbling with an implementation of the Jolt.Functional library, which includes some C++-like functor manipulators (e.g. &lt;span style="font-family:Courier New;"&gt;std::bind&lt;/span&gt;, functor composition, among others), and I thought it would be diligent to describe the motivation behind this tasks by showing what anonymous methods and lambda expressions really look like in MSIL.&lt;/p&gt;  &lt;p&gt;For the purposes of this article, I will be analyzing the output of the C# 3.0 compiler.  Your .NET compiler may output something different, but at the time of writing this I suspect that the output will be similar as there are no native MSIL constructs to represent an anonymous method (and as you may see below, in all likelihood there is no reason to support such constructs).&lt;/p&gt;  &lt;p&gt;&lt;u&gt;MSIL Representation of Anonymous Methods&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;The C# 3.0 &lt;a href="http://msdn.microsoft.com/en-us/library/0yw3tz5k.aspx"&gt;anonymous method syntax&lt;/a&gt; provides a convenient way for inlining method declarations within the body of other methods.  To declare an anonymous method, you can use either the &lt;span style="font-family:Courier New;"&gt;delegate&lt;/span&gt; keyword or the less cumbersome lambda expression syntax.  The latter case is preferred as the compiler can generally infer the types of the method arguments from the usage of the expression.  Here is an example using both syntaxes to declare a predicate that determines if a given integer is equal to 100.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;class FunctorExploration&lt;br /&gt;{&lt;br /&gt;   void CreateFunctors()&lt;br /&gt;   {&lt;br /&gt;       Predicate&amp;lt;int&amp;gt; isOneHundred = value =&amp;gt; value == 100;&lt;br /&gt;       Predicate&amp;lt;int&amp;gt; is100 = delegate(int value) { return value == 100; };&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Both of the given syntaxes present the illusion that an inline method is created with local method scope.  However, since MSIL has no notion of an anonymous or inline method declaration, the compiler’s transformation of this source results in MSIL that is semantically different.  As a software developer, it is important to be aware of these differences as they may affect expected performance.  Here is the MSIL representation of the &lt;span style="font-family:Courier New;"&gt;CreateFunctors()&lt;/span&gt; method, with only one of the predicate declarations.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: text"&gt;&lt;br /&gt;.method private hidebysig instance void CreateFunctors() cil managed&lt;br /&gt;{&lt;br /&gt;   .maxstack 3&lt;br /&gt;   .locals init (&lt;br /&gt;       [0] class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; isOneHundred)&lt;br /&gt;   L_0000: nop&lt;br /&gt;   L_0001: ldsfld class mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate1&lt;br /&gt;   L_0006: brtrue.s L_001b&lt;br /&gt;   L_0008: ldnull&lt;br /&gt;   L_0009: ldftn bool FunctorExploration.FunctorExploration::&amp;lt;createfunctors&amp;gt;b__0(int32)&lt;br /&gt;   L_000f: newobj instance void [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt;::.ctor(object, native int)&lt;br /&gt;   L_0014: stsfld class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate1&lt;br /&gt;   L_0019: br.s L_001b&lt;br /&gt;   L_001b: ldsfld class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate1&lt;br /&gt;   L_0020: stloc.0&lt;br /&gt;   L_0021: ret&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This function first attempts to load the value of the static field &lt;span style="font-family:Courier New;"&gt;CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate1&lt;/span&gt; on to the evaluation stack.  If the value is null, then the static field is initialized to a delegate that refers to our &lt;span style="font-family:Courier New;"&gt;isOneHundred&lt;/span&gt; predicate function.  The method referred to by the delegate is given as &lt;span style="font-family:Courier New;"&gt;FunctorExploration::b__0(int32)&lt;/span&gt;, which is a compiler-generated method that contains our predicate implementation.  Once the cache look-up is completed, the value of the static field is assigned to the local variable &lt;span style="font-family:Courier New;"&gt;isOneHundred&lt;/span&gt;.  Here is an abbreviated version of the MSIL that declares the &lt;span style="font-family:Courier New;"&gt;FunctorExploration&lt;/span&gt; class.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: text"&gt;&lt;br /&gt;.class private auto ansi beforefieldinit FunctorExploration&lt;br /&gt;   extends [mscorlib]System.Object&lt;br /&gt;{&lt;br /&gt;   .method private hidebysig static bool &amp;lt;createfunctors&amp;gt;b__0(int32 'value') cil managed&lt;br /&gt;   {&lt;br /&gt;       .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()&lt;br /&gt;       .maxstack 2&lt;br /&gt;       .locals init (&lt;br /&gt;           [0] bool CS$1$0000)&lt;br /&gt;       L_0000: ldarg.0&lt;br /&gt;       L_0001: ldc.i4.s 100&lt;br /&gt;       L_0003: ceq&lt;br /&gt;       L_0005: stloc.0&lt;br /&gt;       L_0006: br.s L_0008&lt;br /&gt;       L_0008: ldloc.0&lt;br /&gt;       L_0009: ret&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   .method private hidebysig instance void CreateFunctors() cil managed { }&lt;br /&gt;&lt;br /&gt;   .field private static class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate1&lt;br /&gt;   {&lt;br /&gt;       .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The purpose of the cached delegate is to make sure that there is only ever one instance of it in your code.  Whenever you pass the delegate around, you will always refer to the instance held in the static memory of the class.  Furthermore, there is no way to access this instance without using runtime reflection; the compiler and IDE hide all of the generated code from you.&lt;/p&gt;  &lt;p&gt;What happens if a method contains two or more anonymous method declarations?  If you surmised that the generated code depicted above is appropriately emitted for each declaration, then you are correct.  What is interesting is that if two anonymous methods are functionally equivalent (as in the first example), then the compiler will duplicate the method implementation, static field, and code to initialize the static field.  Here is an abbreviated version of the MSIL that declares the &lt;span style="font-family:Courier New;"&gt;FunctorExploration&lt;/span&gt; class from the initial example containing two predicates.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: text"&gt;&lt;br /&gt;.class private auto ansi beforefieldinit FunctorExploration&lt;br /&gt;   extends [mscorlib]System.Object&lt;br /&gt;{&lt;br /&gt;   .method private hidebysig static bool &amp;lt;createfunctors&amp;gt;b__0(int32 'value') cil managed&lt;br /&gt;   {&lt;br /&gt;       .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()&lt;br /&gt;       .maxstack 2&lt;br /&gt;       .locals init (&lt;br /&gt;           [0] bool CS$1$0000)&lt;br /&gt;       L_0000: ldarg.0&lt;br /&gt;       L_0001: ldc.i4.s 100&lt;br /&gt;       L_0003: ceq&lt;br /&gt;       L_0005: stloc.0&lt;br /&gt;       L_0006: br.s L_0008&lt;br /&gt;       L_0008: ldloc.0&lt;br /&gt;       L_0009: ret&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   .method private hidebysig static bool &amp;lt;createfunctors&amp;gt;b__1(int32 'value') cil managed&lt;br /&gt;   {&lt;br /&gt;       .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()&lt;br /&gt;       .maxstack 2&lt;br /&gt;       .locals init (&lt;br /&gt;           [0] bool CS$1$0000)&lt;br /&gt;       L_0000: nop&lt;br /&gt;       L_0001: ldarg.0&lt;br /&gt;       L_0002: ldc.i4.s 100&lt;br /&gt;       L_0004: ceq&lt;br /&gt;       L_0006: stloc.0&lt;br /&gt;       L_0007: br.s L_0009&lt;br /&gt;       L_0009: ldloc.0&lt;br /&gt;       L_000a: ret&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   .method private hidebysig instance void CreateFunctors() cil managed&lt;br /&gt;   {&lt;br /&gt;       .maxstack 3&lt;br /&gt;       .locals init (&lt;br /&gt;           [0] class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; isOneHundred,&lt;br /&gt;           [1] class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; is100)&lt;br /&gt;       L_0000: nop&lt;br /&gt;       L_0001: ldsfld class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate2&lt;br /&gt;       L_0006: brtrue.s L_001b&lt;br /&gt;       L_0008: ldnull&lt;br /&gt;       L_0009: ldftn bool FunctorExploration.FunctorExploration::&amp;lt;createfunctors&amp;gt;b__0(int32)&lt;br /&gt;       L_000f: newobj instance void [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt;::.ctor(object, native int)&lt;br /&gt;       L_0014: stsfld class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate2&lt;br /&gt;       L_0019: br.s L_001b&lt;br /&gt;       L_001b: ldsfld class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate2&lt;br /&gt;       L_0020: stloc.0&lt;br /&gt;       L_0021: ldsfld class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate3&lt;br /&gt;       L_0026: brtrue.s L_003b&lt;br /&gt;       L_0028: ldnull&lt;br /&gt;       L_0029: ldftn bool FunctorExploration.FunctorExploration::&amp;lt;createfunctors&amp;gt;b__1(int32)&lt;br /&gt;       L_002f: newobj instance void [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt;::.ctor(object, native int)&lt;br /&gt;       L_0034: stsfld class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate3&lt;br /&gt;       L_0039: br.s L_003b&lt;br /&gt;       L_003b: ldsfld class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; FunctorExploration.FunctorExploration::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate3&lt;br /&gt;       L_0040: stloc.1&lt;br /&gt;       L_0041: ret&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   .field private static class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate2&lt;br /&gt;   {&lt;br /&gt;       .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   .field private static class [mscorlib]System.Predicate`1&amp;lt;int32&amp;gt; CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate3&lt;br /&gt;   {&lt;br /&gt;       .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Since anonymous methods are local to a function at design time, they may also access other local variables that share the same scope.  Let us generalize our functor to test for equality as follows.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;class FunctorExploration&lt;br /&gt;{&lt;br /&gt;   void CreateEqualityPredicate&amp;lt;TValue&amp;gt;(TValue predicateConstant)&lt;br /&gt;   {&lt;br /&gt;       Predicate&amp;lt;TValue&amp;gt; equals = value =&amp;gt; value.Equals(predicateConstant);&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;When the compiler encounters this type of anonymous method declaration, it emits code that is substantially different from the previously shown static method cases.  Here is the MSIL representation of the &lt;span style="font-family:Courier New;"&gt;CreateEqualityPredicate()&lt;/span&gt; method.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: text"&gt;&lt;br /&gt;.method private hidebysig instance void CreateEqualityPredicate&amp;lt;TValue&amp;gt;(!!TValue predicateConstant) cil managed&lt;br /&gt;{&lt;br /&gt;   .maxstack 3&lt;br /&gt;   .locals init (&lt;br /&gt;       [0] class [mscorlib]System.Predicate`1&amp;lt;!!TValue&amp;gt; equals,&lt;br /&gt;       [1] class FunctorExploration.FunctorExploration/&amp;lt;&amp;gt;c__DisplayClass1&amp;lt;!!TValue&amp;gt; CS$&amp;lt;&amp;gt;8__locals2)&lt;br /&gt;   L_0000: newobj instance void FunctorExploration.FunctorExploration/&amp;lt;&amp;gt;c__DisplayClass1&amp;lt;!!TValue&amp;gt;::.ctor()&lt;br /&gt;   L_0005: stloc.1&lt;br /&gt;   L_0006: ldloc.1&lt;br /&gt;   L_0007: ldarg.1&lt;br /&gt;   L_0008: stfld !0 FunctorExploration.FunctorExploration/&amp;lt;&amp;gt;c__DisplayClass1&amp;lt;!!TValue&amp;gt;::predicateConstant&lt;br /&gt;   L_000d: nop&lt;br /&gt;   L_000e: ldloc.1&lt;br /&gt;   L_000f: ldftn instance bool FunctorExploration.FunctorExploration/&amp;lt;&amp;gt;c__DisplayClass1&amp;lt;!!TValue&amp;gt;::&amp;lt;CreateEqualityPredicate&amp;gt;b__0(!0)&lt;br /&gt;   L_0015: newobj instance void [mscorlib]System.Predicate`1&amp;lt;!!TValue&amp;gt;::.ctor(object, native int)&lt;br /&gt;   L_001a: stloc.0&lt;br /&gt;   L_001b: nop&lt;br /&gt;   L_001c: ret&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This method first instantiates the compiler generated type &lt;span style="font-family:Courier New;"&gt;FunctorExploration/&amp;lt;&amp;gt;c__DisplayClass1&amp;lt;!!TValue&amp;gt;&lt;/span&gt; (a nested type), and then proceeds to initialize a field on this type instance with the value of the local variable of interest.  The &lt;span style="font-family:Courier New;"&gt;equals&lt;/span&gt; predicate is then initialized from a compiler generated method given as &lt;span style="font-family:Courier New;"&gt;&amp;lt;&amp;gt;c__DisplayClass1&amp;lt;!!TValue&amp;gt;::&amp;lt;CreateEqualityPredicate&amp;gt;b__0(!TValue 'value').&lt;/span&gt;  Here is an abbreviated version of the MSIL that represents the compiler-generated type.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: text"&gt;&lt;br /&gt;.class auto ansi sealed nested private beforefieldinit &amp;lt;&amp;gt;c__DisplayClass1&amp;lt;TValue&amp;gt;&lt;br /&gt;   extends [mscorlib]System.Object&lt;br /&gt;{&lt;br /&gt;   .method public hidebysig instance bool &amp;lt;CreateEqualityPredicate&amp;gt;b__0(!TValue 'value') cil managed&lt;br /&gt;   {&lt;br /&gt;       .maxstack 2&lt;br /&gt;       .locals init (&lt;br /&gt;           [0] bool CS$1$0000)&lt;br /&gt;       L_0000: ldarga.s 'value'&lt;br /&gt;       L_0002: ldarg.0&lt;br /&gt;       L_0003: ldfld !0 FunctorExploration.FunctorExploration/&amp;lt;&amp;gt;c__DisplayClass1&amp;lt;!TValue&amp;gt;::predicateConstant&lt;br /&gt;       L_0008: box !TValue&lt;br /&gt;       L_000d: constrained !TValue&lt;br /&gt;       L_0013: callvirt instance bool [mscorlib]System.Object::Equals(object)&lt;br /&gt;       L_0018: stloc.0&lt;br /&gt;       L_0019: br.s L_001b&lt;br /&gt;       L_001b: ldloc.0&lt;br /&gt;       L_001c: ret&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   .field public !TValue predicateConstant&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The new type is created to give the anonymous method implementation its own reference to the local variable of interest.  Whenever &lt;span style="font-family:Courier New;"&gt;CreateEqualityPredicate()&lt;/span&gt; is invoked, a new instance of the type is returned, initialized with whatever value is given as a parameter to our function.  The delegate can no longer be static since we are dealing with instance data.&lt;/p&gt;  &lt;p&gt;What happens when we declare multiple delegates in this fashion?  As in the corresponding example, a new type will be created for each anonymous method that uses a local variable from an accessible sibling scope.  Again, code duplication arises if there are two anonymous method declarations that are equivalent in functionality.  Also, as mentioned before, there is no way to access the generated entities at design time without using runtime reflection.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Jolt.Functional Motivation&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;The introduction of &lt;a href="http://msdn.microsoft.com/en-us/netframework/aa904594.aspx"&gt;Linq&lt;/a&gt; in the .NET Framework 3.5 has made anonymous methods and important language feature.  Without them, it is very tedious to define predicates in your code using function declaration syntax, then refer to them in your Linq filter criterion.  However, the advantage taking such an approach is that one is more likely to notice patterns in the predicate code and thus have the opportunity to refactor for code reuse.  This is not possible with compiler-generated code, and each time you introduce an anonymous method, you increase the amount of code duplication that may occur.&lt;/p&gt;  &lt;p&gt;The Jolt.Functional library aims to minimize the amount of compiler-generated code by promoting functor reuse through the use of &lt;em&gt;generic delegate declarations&lt;/em&gt; for commonly-used delegates, along with &lt;em&gt;generic delegate factory methods&lt;/em&gt; for manipulating existing functions.  Here are some examples of these types of constructs.&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Creation of idempotent functions (returning a constant value for any input)&lt;/li&gt;&lt;li&gt;Predefined idempotent functions (true for all, false for all)&lt;/li&gt;&lt;li&gt;Parameter binding and function composition&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Courier New;"&gt;Predicate&amp;lt;T&amp;gt;&lt;/span&gt; adaptor for &lt;span style="font-family:Courier New;"&gt;Func&amp;lt;T, bool&amp;gt;&lt;/span&gt; (and vice versa)&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Courier New;"&gt;Action&amp;lt;T&amp;gt;&lt;/span&gt; adaptor for &lt;span style="font-family:Courier New;"&gt;Func&amp;lt;T, TResult&amp;gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;To illustrate the benefit of such constructs, consider the generic &lt;span style="font-family:Courier New;"&gt;CreateEqualityPredicate()&lt;/span&gt; method from a previous example.  This method creates a predicate for each invocation.  However since its implementation is generic, the compiler has only generated one implementation of the predicate method and supporting types.  Compare this with inlining many lambda expressions that test for various types of equality.  The functionality of the code is the same, but the MSIL and assembly size has grown dramatically!&lt;/p&gt;  &lt;p&gt;For those concerned about assembly code bloat from anonymous methods, the Jolt.Functional library will help by reducing the amount duplicate compiler-generated code in your program.  Also, if your language does not support anonymous methods, the Jolt.Functional library can help you organize your method declarations so that they may be combined and reused to form more complicated expressions.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-470711060375640446?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pTf8STL5V7oPhOYflAiz_TVnLdw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pTf8STL5V7oPhOYflAiz_TVnLdw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pTf8STL5V7oPhOYflAiz_TVnLdw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pTf8STL5V7oPhOYflAiz_TVnLdw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=4ZxtwHcRDdg:muq-sa_nX7E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=4ZxtwHcRDdg:muq-sa_nX7E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=4ZxtwHcRDdg:muq-sa_nX7E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=4ZxtwHcRDdg:muq-sa_nX7E:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/4ZxtwHcRDdg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/470711060375640446/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=470711060375640446" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/470711060375640446?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/470711060375640446?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/4ZxtwHcRDdg/anonymous-methods-and-jolt-functors.html" title="Anonymous Methods and Jolt Functors: Behind the Scenes" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/04/anonymous-methods-and-jolt-functors.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcMQX0zfyp7ImA9WxVaFUg.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-614361518766618038</id><published>2009-04-12T10:02:00.001-07:00</published><updated>2009-04-12T10:08:00.387-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-12T10:08:00.387-07:00</app:edited><title>Wiki Documentation Formatting</title><content type="html">Please bear with the poor formatting in the wiki documentation for &lt;a href="http://jolt.codeplex.com"&gt;Jolt.NET&lt;/a&gt;.  Sometime within the past few weeks, the &lt;a href="http://www.codeplex.com"&gt;CodePlex&lt;/a&gt; wiki parser was changed and consequenly any inline formatting is being incorrectly parsed.  This is causing certain style formats to run through to the end of the document, and other inline code formatting to be applied on a new line.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These change are out of my control and hopefully this will be resolved very quickly!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-614361518766618038?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/L_JmTe8DizvS14yZIj_yZLbPAo8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/L_JmTe8DizvS14yZIj_yZLbPAo8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/L_JmTe8DizvS14yZIj_yZLbPAo8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/L_JmTe8DizvS14yZIj_yZLbPAo8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=z_2SNeGsW3A:3k8fnCnyrJc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=z_2SNeGsW3A:3k8fnCnyrJc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=z_2SNeGsW3A:3k8fnCnyrJc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=z_2SNeGsW3A:3k8fnCnyrJc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/z_2SNeGsW3A" height="1" width="1"/&gt;</content><link rel="related" href="http://codeplex.codeplex.com/Thread/View.aspx?ThreadId=53036" title="Wiki Documentation Formatting" /><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/614361518766618038/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=614361518766618038" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/614361518766618038?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/614361518766618038?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/z_2SNeGsW3A/wiki-documentation-formatting.html" title="Wiki Documentation Formatting" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/04/wiki-documentation-formatting.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQCQ38_eCp7ImA9WxVbEU8.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-8302604824214847964</id><published>2009-03-26T21:32:00.001-07:00</published><updated>2009-03-26T21:32:42.140-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-26T21:32:42.140-07:00</app:edited><title>Source Code Reorganization – Part One</title><content type="html">&lt;p&gt;I just completed the first batch of source code reorganization on the Jolt 0.3 &lt;a href="http://jolt.codeplex.com/WorkItem/AdvancedList.aspx"&gt;work item&lt;/a&gt; list and committed it to &lt;a href="http://jolt.codeplex.com/SourceControl/changeset/view/18919"&gt;revision #18919&lt;/a&gt;.&amp;#160; All code pertaining to the implementation and support of the &lt;font face="Courier New"&gt;FiniteStateMachine&lt;/font&gt; (FSM) class is now in the the Jolt.Automata assembly, and similarly, all FSM-related test code has moved to the Jolt.Automata.Test assembly.&amp;#160; The following notes summarize all the breaking changes that were introduced as part of moving the source code.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;All FSM-related types that were previously in the &lt;strong&gt;Jolt&lt;/strong&gt; namespace are now in the &lt;strong&gt;Jolt.Automata&lt;/strong&gt; namespace&lt;/li&gt;   &lt;li&gt;No types have been renamed&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Please refer to “&lt;a href="http://joltdev.blogspot.com/2009/03/joltnet-restructuring-and-future.html"&gt;Jolt.NET Restructuring and Future Features&lt;/a&gt;” for an overview of the source-code reorganization tasks.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-8302604824214847964?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/IW2TvFi8TWh-pYXmtrfS3iR73a4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IW2TvFi8TWh-pYXmtrfS3iR73a4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/IW2TvFi8TWh-pYXmtrfS3iR73a4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IW2TvFi8TWh-pYXmtrfS3iR73a4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=pFZee8s1GEI:WJTGqx7dl1A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=pFZee8s1GEI:WJTGqx7dl1A:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=pFZee8s1GEI:WJTGqx7dl1A:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=pFZee8s1GEI:WJTGqx7dl1A:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/pFZee8s1GEI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/8302604824214847964/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=8302604824214847964" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/8302604824214847964?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/8302604824214847964?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/pFZee8s1GEI/source-code-reorganization-part-one.html" title="Source Code Reorganization – Part One" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/03/source-code-reorganization-part-one.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQESH86cSp7ImA9WxVUGUk.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-7772868225052986575</id><published>2009-03-24T17:27:00.000-07:00</published><updated>2009-03-24T17:51:49.119-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-24T17:51:49.119-07:00</app:edited><title>Jolt.NET 0.2 Release</title><content type="html">&lt;div&gt;Good day!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This morning, I committed source &lt;a href="http://jolt.codeplex.com/SourceControl/changeset/view/18896"&gt;revision #18896&lt;/a&gt; containing the final feature work for the Jolt.NET 0.2 release.  This work was completed last week, but I didn't get a chance to upload the changes as I was in a rush to catch a flight for a trip.  During my travels, I had little time to access the internet and prepare the release documentation, so I had to wait until my return home.  Sorry for the delay!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Jolt.NET 0.2 contains the following new features:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;A &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.FSM&amp;amp;referringTitle=Jolt"&gt;generic finite state machine&lt;/a&gt; implementation&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Programmatic querying of &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.XmlDocComments&amp;amp;referringTitle=Jolt"&gt;XML doc comments&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;XML doc comment auto-creation for types generated by the &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Testing.CodeGeneration.Proxy&amp;amp;referringTitle=Jolt.Testing"&gt;Jolt.Testing library&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are also some other maintenance-related changes included in the release, all of which can be viewed on the &lt;a href="http://jolt.codeplex.com/WorkItem/AdvancedList.aspx"&gt;work item&lt;/a&gt; page.  Please visit the &lt;a href="http://jolt.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=20320"&gt;release page&lt;/a&gt; for download options.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tomorrow, I will be creating the initial set of work items for the Jolt.NET 0.3 release, most of which were discussed in my &lt;a href="http://joltdev.blogspot.com/2009/03/joltnet-restructuring-and-future.html"&gt;previous post&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-7772868225052986575?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Orl3OeJR7Er0gERrlTfBMTX9hK4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Orl3OeJR7Er0gERrlTfBMTX9hK4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Orl3OeJR7Er0gERrlTfBMTX9hK4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Orl3OeJR7Er0gERrlTfBMTX9hK4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=DoTTW5YNqRc:hRCsIigadf8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=DoTTW5YNqRc:hRCsIigadf8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=DoTTW5YNqRc:hRCsIigadf8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=DoTTW5YNqRc:hRCsIigadf8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/DoTTW5YNqRc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/7772868225052986575/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=7772868225052986575" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/7772868225052986575?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/7772868225052986575?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/DoTTW5YNqRc/joltnet-02-release.html" title="Jolt.NET 0.2 Release" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/03/joltnet-02-release.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4NRnsyeip7ImA9WxJTE04.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-3489589462008660205</id><published>2009-03-13T22:26:00.001-07:00</published><updated>2009-04-21T11:19:57.592-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-21T11:19:57.592-07:00</app:edited><title>Jolt.NET Restructuring and Future Features</title><content type="html">&lt;p&gt;During my regular day-job and while I work on the &lt;a href="http://www.codeplex.com/jolt"&gt;Jolt.NET library&lt;/a&gt;, I regularly take notes as to what to include in future library releases.  Sometimes, I post the notes immediately to the project site in the form of a work item.  In this case, the work item will usually contain information about a required change in design of an existing feature, or some planned analysis that assures intended feature functionality.  When I don’t post my notes, it is usually because they refer to an incomplete feature idea (i.e. how the feature should work), and I don’t post them so that I can keep focused on working to complete the currently planned release.&lt;/p&gt;  &lt;p&gt;This post will cover some of the upcoming new features for Jolt.NET as well as some needed library reorganization.  You can expect future posts with this theme as the active implementation of a pending release nears completion.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;New Assemblies&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;The &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt&amp;amp;referringTitle=Home"&gt;Jolt&lt;/a&gt; assembly is designed to be the analog of the &lt;a href="http://en.wikipedia.org/wiki/.NET_Framework#Class_library"&gt;mscorlib.dll&lt;/a&gt; assembly from the .NET Framework.  It contains the commonly used types that generally don’t fit anywhere else in the library, and also serves as a core assembly to be used by others within the library.  For simplicity and ease of use, I’d like Jolt.dll to be free of both internal and external dependencies, for violating this guideline means that any assembly linking to Jolt.dll incurs extra baggage which it may or may not use.  Consequently, the &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.FSM&amp;amp;referringTitle=Jolt"&gt;&lt;span style="font-family:Courier New;"&gt;FiniteStateMachine&lt;/span&gt;&lt;/a&gt; (FSM) class (and its helpers) must be moved to a new assembly as they incur a dependency to &lt;a href="http://www.codeplex.com/quickgraph"&gt;QuickGraph&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;A similar approach must also be taken when implementing the features that enable translation of an FSM to &lt;a href="http://store.microsoft.com/microsoft/Automatic-Graph-Layout-2007/product/4DD40C40"&gt;MSAGL&lt;/a&gt; and &lt;a href="http://research.microsoft.com/en-us/downloads/f1303e46-965f-401a-87c3-34e1331d32c5/default.aspx"&gt;GLEE&lt;/a&gt; graphs since the MSAGL and GLEE assemblies are generally not redistributable.  QuickGraph provides separate assemblies that enable use of these frameworks, avoiding runtime errors in the core library when the frameworks are not present.  I plan to adopt a similar approach for the new Jolt FSM assembly.  Also, you will note that the work items for the FSM translation features have been moved out of the &lt;a href="http://www.codeplex.com/jolt/Release/ProjectReleases.aspx?ReleaseId=20320"&gt;Jolt 0.2 release&lt;/a&gt; as I want to perform all of the reorganization at the same time.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Functors&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;This is a task I’ve been eager to take on for some time now, and think it will add great value to the Jolt.NET library.  The goal is to provide predefined functors that eliminate the need for redefining the same kinds of anonymous delegate (or lambda expressions) over and over.  Redefinition, albeit very compact in syntax, often leads to code bloat in the assembly in the form of non-compact IL.  To illustrate, consider the following code that uses two identical lambda expressions to represent a predicate.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;using System;&lt;br /&gt;&lt;br /&gt;void CreateFunctors()&lt;br /&gt;{&lt;br /&gt;  Predicate&amp;lt;int&amp;gt; isEven = x =&amp;gt; x % 2 == 0;&lt;br /&gt;  Func&amp;lt;int,bool&amp;gt; isNotOdd = x =&amp;gt; x % 2 == 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The resulting IL for this function will yield two additional methods, both identical in functionality and representing each lambda expression.  If you use an optimizing IL compiler, you may be in luck as the compiler &lt;em&gt;might&lt;/em&gt; generate the desired compact version of the code.  I’ll discuss this problem further in a future blog post.&lt;/p&gt;&lt;p&gt;Which functors will help reduce code bloat?  I’ve noted the following, which are used extensively in the Jolt libraries, and can be represented as either constructed or open constructed forms of the &lt;span style="font-family:Courier New;"&gt;Action&amp;lt;&amp;gt;&lt;/span&gt; and &lt;span style="font-family:Courier New;"&gt;Func&amp;lt;&amp;gt;&lt;/span&gt; delegate variants.&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Idempotency&lt;/strong&gt; function: f(x) = c, for all x and a predefined constant c&lt;ul&gt;      &lt;li&gt;Example: f(x) = true, for all x&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;  &lt;li&gt;&lt;strong&gt;Identity&lt;/strong&gt; function: f(x) = x, for all x&lt;/li&gt;&lt;li&gt;&lt;strong&gt;No-op&lt;/strong&gt; function: f(x) = void; for all x&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In addition to these predefined functors, the following utilities will assist reusing existing delegates to create new ones.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Adaptor&lt;/strong&gt; for &lt;span style="font-family:Courier New;"&gt;Func&amp;lt;&amp;gt;&lt;/span&gt;: ignores return value making it compatible with &lt;span style="font-family:Courier New;"&gt;Action&amp;lt;&amp;gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Functor composition&lt;/strong&gt;: given functions f(x), and g(y), compose a new function h(y) = f(g(y))&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Parameter binding&lt;/strong&gt;: given function f(x, y), bind the first parameter of the function to a constant c, creating a new function g(y) = f(c, y)&lt;ul&gt;      &lt;li&gt;Similarly for the second parameter&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;u&gt;Tuples&lt;/u&gt;&lt;/p&gt;&lt;p&gt;The goal of a tuple is to provide for a light-weight read/write generic container that defines only fields (i.e. no methods).  Instead of explicitly defining a new type each time you need to store a collection of fields, a tuple allows you to specialize it with the desired field types, creating the desired container.  For example, &lt;span style="font-family:Courier New;"&gt;Tuple&amp;lt;int, string&amp;gt;&lt;/span&gt; is a type containing two fields of types &lt;span style="font-family:Courier New;"&gt;int&lt;/span&gt; and &lt;span style="font-family:Courier New;"&gt;string&lt;/span&gt;, respectively.&lt;/p&gt;&lt;p&gt;For those familiar with &lt;a href="http://msdn.microsoft.com/en-us/library/bb397696.aspx"&gt;anonymous types&lt;/a&gt;, tuples may seem redundant .  However, there are some important differences between an anonymous type and a tuple.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The type of the tuple is known at design time&lt;/li&gt;&lt;li&gt;The fields of a tuple are writable&lt;/li&gt;&lt;li&gt;A tuple implements value-based equality semantics&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The tuple implementation will be adapted from the &lt;a href="http://www.boost.org/doc/libs/1_37_0/libs/tuple/doc/tuple_users_guide.html"&gt;Boost Tuple Library&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-3489589462008660205?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/c8gThi78KCECHFGngNX5AtEmzm0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/c8gThi78KCECHFGngNX5AtEmzm0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/c8gThi78KCECHFGngNX5AtEmzm0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/c8gThi78KCECHFGngNX5AtEmzm0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=NWll4rFjtPo:7bcpJeDwObQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=NWll4rFjtPo:7bcpJeDwObQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=NWll4rFjtPo:7bcpJeDwObQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=NWll4rFjtPo:7bcpJeDwObQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/NWll4rFjtPo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/3489589462008660205/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=3489589462008660205" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/3489589462008660205?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/3489589462008660205?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/NWll4rFjtPo/joltnet-restructuring-and-future.html" title="Jolt.NET Restructuring and Future Features" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/03/joltnet-restructuring-and-future.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEINSHY6cCp7ImA9WxJTE04.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-6939041514679106236</id><published>2009-03-12T22:32:00.001-07:00</published><updated>2009-04-21T10:56:39.818-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-21T10:56:39.818-07:00</app:edited><title>Xml Doc Comment Transformations</title><content type="html">&lt;p&gt;The &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Testing"&gt;Jolt.Testing&lt;/a&gt; library now supports creating XML doc comments for a generated proxy and interface type, as well as aggregating such XML for a generated assembly.&amp;#160; The code is made available by &lt;a href="http://jolt.codeplex.com/SourceControl/changeset/view/18785"&gt;revision 18785&lt;/a&gt;, and usage examples are posted in the &lt;a href="http://jolt.codeplex.com/Wiki/View.aspx?title=Jolt.Testing.CodeGeneration.Proxy&amp;amp;referringTitle=Jolt.Testing"&gt;library documentation&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The implementation of this feature utilizes the &lt;font face="Courier New"&gt;XmlDocCommentReader&lt;/font&gt; class detailed in my &lt;a href="http://joltdev.blogspot.com/2009/01/thinking-about-xml-documentation.html"&gt;previous post&lt;/a&gt;, and also provides configuration to turn the feature on and off.&amp;#160; When creating the XML doc comments for the new types, a simple transformation is performed on the existing XML, replacing the type name of the real subject type with that of the proxy or interface.&amp;#160; For simplicity, all other XML data&amp;#160; participating in the transformation is left untouched.&amp;#160; The following snippet depicts this process.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;!-- Original XML doc comments. --&gt;&lt;br /&gt;&lt;doc&gt;&lt;br /&gt;  &lt;assembly&gt;&lt;br /&gt;    &lt;name&gt;mscorlib&lt;/name&gt;&lt;br /&gt;  &lt;/assembly&gt;&lt;br /&gt;  &lt;members&gt;&lt;br /&gt;    &lt;member name="T:System.IO.File"&gt;&lt;br /&gt;      &lt;summary&gt;&lt;br /&gt;                    Provides static methods for the creation, copying, deletion, moving, and opening of files, and aids in the creation of &lt;see cref="T:System.IO.FileStream" /&gt; objects.&lt;br /&gt;                &lt;/summary&gt;&lt;br /&gt;      &lt;filterpriority&gt;1&lt;/filterpriority&gt;&lt;br /&gt;    &lt;/member&gt;&lt;br /&gt;  &lt;/members&gt;&lt;br /&gt;&lt;/doc&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- Transformed XML doc comments. --&gt;&lt;br /&gt;&lt;doc&gt;&lt;br /&gt;  &lt;assembly&gt;&lt;br /&gt;    &lt;name&gt;Jolt.GeneratedCode&lt;/name&gt;&lt;br /&gt;  &lt;/assembly&gt;&lt;br /&gt;  &lt;members&gt;&lt;br /&gt;    &lt;member name="T:Jolt.GeneratedCode.System.IO.IFile"&gt;&lt;br /&gt;      &lt;summary&gt;&lt;br /&gt;                    Provides static methods for the creation, copying, deletion, moving, and opening of files, and aids in the creation of &lt;see cref="T:System.IO.FileStream" /&gt; objects.&lt;br /&gt;                &lt;/summary&gt;&lt;br /&gt;      &lt;filterpriority&gt;1&lt;/filterpriority&gt;&lt;br /&gt;    &lt;/member&gt;&lt;br /&gt;    &lt;member name="T:Jolt.GeneratedCode.System.IO.FileProxy"&gt;&lt;br /&gt;      &lt;summary&gt;&lt;br /&gt;                    Provides static methods for the creation, copying, deletion, moving, and opening of files, and aids in the creation of &lt;see cref="T:System.IO.FileStream" /&gt; objects.&lt;br /&gt;                &lt;/summary&gt;&lt;br /&gt;      &lt;filterpriority&gt;1&lt;/filterpriority&gt;&lt;br /&gt;    &lt;/member&gt;&lt;br /&gt;  &lt;/members&gt;&lt;br /&gt;&lt;/doc&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Note that the resulting documentation may contain text that is specific to the real subject type, and not very applicable to the proxy or interface types.&amp;#160; This is a minor inconvenience and I believe that many developers will simply ignore it, if not even notice it all.&amp;#160; The big win in implementing this feature is getting parameter information for proxy and interface functions, and Intellisense in general within an IDE.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-6939041514679106236?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/u2tmULg1wgfzHnPEQAXlwb5rplY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u2tmULg1wgfzHnPEQAXlwb5rplY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/u2tmULg1wgfzHnPEQAXlwb5rplY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u2tmULg1wgfzHnPEQAXlwb5rplY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Fjj2hrIZbx4:8k_ZPeRswNQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Fjj2hrIZbx4:8k_ZPeRswNQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=Fjj2hrIZbx4:8k_ZPeRswNQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Fjj2hrIZbx4:8k_ZPeRswNQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/Fjj2hrIZbx4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/6939041514679106236/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=6939041514679106236" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/6939041514679106236?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/6939041514679106236?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/Fjj2hrIZbx4/xml-doc-comment-transformations.html" title="Xml Doc Comment Transformations" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/03/xml-doc-comment-transformations.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEDSHoycSp7ImA9WxJTE04.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-5893360321227868648</id><published>2009-02-19T00:17:00.001-08:00</published><updated>2009-04-21T10:57:59.499-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-21T10:57:59.499-07:00</app:edited><title>ProxyTypeBuilder Usability Issue</title><content type="html">&lt;p&gt;While working on implementing utilities to parse and read an XML doc comment file, I came across the need to abstract the file system for the purpose of testing.  This was a perfect time to use the &lt;a href="http://www.codeplex.com/jolt/Wiki/View.aspx?title=Jolt.Testing&amp;amp;referringTitle=Home"&gt;Jolt.Testing&lt;/a&gt; library and generate an assembly with a proxy and interface to the static &lt;span style="font-family:Courier New;"&gt;System.IO.File&lt;/span&gt; class!  My intent was to write the following code.&lt;/p&gt;    &lt;pre class="brush: csharp"&gt;using Rhino.Mocks;&lt;br /&gt;using Jolt.Testing.Generated.System.IO;&lt;br /&gt;using System.IO;&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;void FileInteractions()&lt;br /&gt;{&lt;br /&gt; With.Mocks(delegate&lt;br /&gt; {&lt;br /&gt;   IFile fileProxy = Mocker.Current.CreateMock&amp;lt;IFile&amp;gt;();&lt;br /&gt;&lt;br /&gt;   Stream fileContents = new MemoryStream(/* stream data */);&lt;br /&gt;   Expect.Call(fileProxy.Open("filename")).Return(fileContents);&lt;br /&gt;   Mocker.Current.ReplayAll();&lt;br /&gt;&lt;br /&gt;   FileReader reader = new FileReader(fileProxy);&lt;br /&gt;   type.DoWork("filename");&lt;br /&gt; });&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;  &lt;p&gt;This is the example I use in my documentation (creating the &lt;span style="font-family:Courier New;"&gt;IFile&lt;/span&gt; interface), and was the prime motivation for creating the &lt;a href="http://www.codeplex.com/jolt/Wiki/View.aspx?title=Jolt.Testing&amp;amp;referringTitle=Home"&gt;Jolt.Testing&lt;/a&gt; library.  In this test, the file system is never accessed and the IO operation (&lt;span style="font-family:Courier New;"&gt;Open&lt;/span&gt;) happens in memory.  However, there is a fundamental problem with this code – &lt;em&gt;it won’t compile&lt;/em&gt;!  Can you see why?&lt;/p&gt;  &lt;p&gt;When I saw the compilation error, my heart sank.  The &lt;span style="font-family:Courier New;"&gt;Open&lt;/span&gt; method returns a &lt;span style="font-family:Courier New;"&gt;FileStream&lt;/span&gt; object, not a &lt;span style="font-family:Courier New;"&gt;Stream&lt;/span&gt; object (the downcast is not guaranteed to work)!  All of a sudden I realized that generating an abstraction to the &lt;span style="font-family:Courier New;"&gt;System.IO.File&lt;/span&gt; class accomplished very little since using the &lt;span style="font-family:Courier New;"&gt;Open&lt;/span&gt; method still requires that you use the file system.  Sure, I could use the &lt;span style="font-family:Courier New;"&gt;OpenText&lt;/span&gt; method which returns a &lt;span style="font-family:Courier New;"&gt;StreamReader&lt;/span&gt; that is wired to my memory stream (and I ultimately did for this test), but there is still a fundamental problem with the usability of the &lt;span style="font-family:Courier New;"&gt;ProxyTypeBuilder&lt;/span&gt; outputs:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;A generated interface contains method signatures with concrete types that are intended to be abstracted by the interface.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;If you think about it, you would never design a base class to a hierarchy and make references to the concrete types within the base class.  Doing so defeats the purpose of creating the base class all together!  The same rationale applies to an interface that generalizes some kind of functionality.  Recall the wisdom from the &lt;a href="http://en.wikipedia.org/wiki/Gang_of_Four_(software)"&gt;GoF&lt;/a&gt;: when possible, code against an abstraction, not a concrete implementation.&lt;/p&gt;  &lt;p&gt;At this point, I thought my implementation was all for naught.  When the shock subsided, I realized that there is flexible solution to the problem, made easy-to-implement by the modularization and design of the &lt;span style="font-family:Courier New;"&gt;ProxyTypeBuilder&lt;/span&gt; class.  The idea to the fix is as follows.  For the &lt;span style="font-family:Courier New;"&gt;ProxyTypeBuilder&lt;/span&gt; methods &lt;span style="font-family:Courier New;"&gt;AddMethod&lt;/span&gt; and &lt;span style="font-family:Courier New;"&gt;AddProperty&lt;/span&gt; (entities that return a value), I will need to add an overload that accepts an override type for the return value.  The functions will validate to the make sure that the given type is indeed a base type of the overridden type prior to generating any code.  When the generated code is executed and the real subject type returns its object, the proxy will return a reference to the object’s base type, which hides the concrete type, and everything works as expected.&lt;/p&gt;  &lt;p&gt;The pros to this solution:&lt;/p&gt;  &lt;ul&gt;&lt;br /&gt; &lt;li&gt;Option to override is flexible, avoiding the incorrect auto-conversion approach.&lt;br /&gt;     &lt;li&gt;It makes sense to change the return value of &lt;span style="font-family:Courier New;"&gt;FileStream&lt;/span&gt; to &lt;span style="font-family:Courier New;"&gt;Stream&lt;/span&gt;, but it doesn’t make sense to change &lt;span style="font-family:Courier New;"&gt;DateTime&lt;/span&gt; to &lt;span style="font-family:Courier New;"&gt;ValueType&lt;/span&gt;.&lt;/li&gt;  &lt;li&gt;Solution extends easily to XML configuration of &lt;span style="font-family:Courier New;"&gt;ProxyAssemblyBuilder&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;The cons to this solution:&lt;/p&gt;  &lt;ul&gt;&lt;br /&gt; &lt;li&gt;Xml documentation for the return value may be incorrect; it may still refer to a concrete type after overriding.&lt;/li&gt; &lt;li&gt;Generated assemblies for the same type are generally incompatible; you can’t swap one with another as the signature of some methods may be different.&lt;/li&gt; &lt;li&gt;Developers may have needed a real reference to the concrete type, and so a downcast is required.&lt;/li&gt; &lt;li&gt;Can’t apply the same idea to method parameters since functions called from the parameters may not exist in the base type.&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;Apart from the parameter issue that requires investigation, my feeling is that the cons to the solution are negligible.  In any case, do let me know what you think.  I plan to start work on this feature after the &lt;a href="http://www.codeplex.com/jolt/Release/ProjectReleases.aspx?ReleaseId=20320"&gt;Jolt 0.2 release&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-5893360321227868648?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/XUVzostqmHHeS1o_bdJhJO93hN4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XUVzostqmHHeS1o_bdJhJO93hN4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/XUVzostqmHHeS1o_bdJhJO93hN4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XUVzostqmHHeS1o_bdJhJO93hN4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=r3TKVYjhrg8:at3jB4lffQE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=r3TKVYjhrg8:at3jB4lffQE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=r3TKVYjhrg8:at3jB4lffQE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=r3TKVYjhrg8:at3jB4lffQE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/r3TKVYjhrg8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/5893360321227868648/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=5893360321227868648" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/5893360321227868648?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/5893360321227868648?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/r3TKVYjhrg8/proxytypebuilder-usability-issue.html" title="ProxyTypeBuilder Usability Issue" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/02/proxytypebuilder-usability-issue.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UDQH4_eCp7ImA9WxVWEE4.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-775727861218967102</id><published>2009-02-19T00:14:00.001-08:00</published><updated>2009-02-19T00:14:31.040-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-19T00:14:31.040-08:00</app:edited><title>More on XML Documentation Comments</title><content type="html">&lt;p&gt;I recently &lt;a href="http://joltdev.blogspot.com/2009/01/thinking-about-xml-documentation.html"&gt;posted&lt;/a&gt; about some of the challenges involved with implementing an algorithm that will locate an XML doc comment file, given a reference to a &lt;font face="Courier New"&gt;System.Reflection.Assembly&lt;/font&gt; object.&amp;#160; Today, I would like to discuss the extent of how this feature will be used and exposed in the &lt;a href="http://www.codeplex.com/jolt/Wiki/View.aspx?title=Jolt&amp;amp;referringTitle=Home"&gt;Jolt&lt;/a&gt; library.&lt;/p&gt;  &lt;p&gt;Initially, I had planned to keep the XML doc comment parsing internal and expose it as a feature of the &lt;font face="Courier New"&gt;ProxyTypeBuilder&lt;/font&gt; class.&amp;#160; As described in &lt;a href="http://www.codeplex.com/jolt/WorkItem/View.aspx?WorkItemId=95"&gt;work item #95&lt;/a&gt;, copying existing XML doc comments to those of the generated interface and proxy type will provide richer Intellisense.&amp;#160; However, while designing the classes that implement this feature, I noticed that they would be better suited as public types as they may be used to solve many XML doc comment parsing tasks.&amp;#160; Consequently, the following use cases will be supported.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Inferring the location of an XML doc comment file from a reference to a &lt;font face="Courier New"&gt;System.Reflection.Assembly&lt;/font&gt; object. &lt;/li&gt;    &lt;li&gt;Obtaining the XML doc comments for a given metadata type (i.e. &lt;font face="Courier New"&gt;System.Type&lt;/font&gt;, &lt;font face="Courier New"&gt;System.Reflection.MethodInfo&lt;/font&gt;, &lt;font face="Courier New"&gt;System.Reflection.ConstructorInfo&lt;/font&gt;, etc…). &lt;/li&gt;    &lt;li&gt;Converting a given metadata type into its XML doc comment string representation. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The code example in the &lt;a href="http://joltdev.blogspot.com/2009/01/thinking-about-xml-documentation.html"&gt;previous post&lt;/a&gt; on this topic gives the syntax example for the first two bullets.&amp;#160; The conversion task allows one to take a &lt;font face="Courier New"&gt;MethodInfo&lt;/font&gt; type for a method such as &lt;font face="Courier New"&gt;void Namespace.MyType.MyMethod&amp;lt;U&amp;gt;(out T t, U u[])&lt;/font&gt; and turn it into the string &lt;font face="Courier New"&gt;“M:Namespace.MyType`0.MyMethod(`0,``0[])”&lt;/font&gt;, which is the key into the XML doc comment data for the corresponding method.&lt;/p&gt;  &lt;p&gt;If you search the web for articles relating to reading or parsing an XML doc comment file, you will see many requests for knowledge on how to transform a .NET metadata type into the corresponding XML documentation.&amp;#160; The proposed &lt;font face="Courier New"&gt;XmlDocCommentReader&lt;/font&gt; class will make this very easy to do.&amp;#160; The conversion functions are geared more towards lower-level development, and they may be used to support the implementation of an XSLT or various XPath queries.&lt;/p&gt;  &lt;p&gt;These features are currently under development and will be ready within a few days (of development time).&amp;#160; Currently, I’m focusing on the testing of all of the possible permutations of generic/array/pointer/ref types that change the resulting key into the XML doc comment member list.&amp;#160; There are plenty of permutations, and a lot more than I had initially expected!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-775727861218967102?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Jz-F7fcwD999iBXe0oCSvRS3mrc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jz-F7fcwD999iBXe0oCSvRS3mrc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Jz-F7fcwD999iBXe0oCSvRS3mrc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jz-F7fcwD999iBXe0oCSvRS3mrc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=iET28s3nw2I:S5aDrBAvru0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=iET28s3nw2I:S5aDrBAvru0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=iET28s3nw2I:S5aDrBAvru0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=iET28s3nw2I:S5aDrBAvru0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/iET28s3nw2I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/775727861218967102/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=775727861218967102" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/775727861218967102?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/775727861218967102?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/iET28s3nw2I/more-on-xml-documentation-comments.html" title="More on XML Documentation Comments" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/02/more-on-xml-documentation-comments.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IFRnczeyp7ImA9WxVQEEo.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-5516052740105407748</id><published>2009-01-26T09:32:00.000-08:00</published><updated>2009-01-27T08:58:37.983-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-27T08:58:37.983-08:00</app:edited><title>GraphML Serialization for FSMs</title><content type="html">As of revision &lt;a href="http://www.codeplex.com/jolt/SourceControl/changeset/view/18123"&gt;18123&lt;/a&gt;, it is now possible to serialize an FSM to &lt;a href="http://graphml.graphdrawing.org/"&gt;GraphML&lt;/a&gt; and perform the inverse deserialization operation.  However, there are some caveats with the current implementation that I will discuss below.  In the mean time, if you would like to review how to use this feature, please refer to the &lt;a href="http://www.codeplex.com/jolt/Wiki/View.aspx?title=Jolt.FSM"&gt;FSM documentation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;Copying Data and Intermediate Types&lt;/span&gt;&lt;div&gt;&lt;br /&gt;When serializing to GraphML, any serilizable data needs to be represented as a primitive type (a numerical or string type).  Furthermore, in order for a property value to be serialized, the &lt;a href="http://www.codeplex.com/quickgraph"&gt;QuickGraph&lt;/a&gt; GraphML serialization facility requires that the property be decorated with &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlattributeattribute.aspx"&gt;XmlAttribute&lt;/a&gt;&lt;/span&gt;.  Unfortunately, implementing support for GraphML serialization wasn't as easy as just decorating some properties with &lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;XmlAttribute&lt;/span&gt; since properties of each state are held in the &lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;FiniteStateMachine&lt;/span&gt; class (start/final state markers).&lt;br /&gt;&lt;br /&gt;To address this issue, I created two intermediate types: one to hold all serializable transition data (&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;GraphMLTransition&lt;/span&gt;), and the other to hold all serializable state data (&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;GraphMLState&lt;/span&gt;).  In essence, each of these types represents the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;lt;node&amp;gt;&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;lt;edge&amp;gt;&lt;/span&gt; GraphML elements.  Each time the FSM is serialized, it is copied into a new graph of the intermediate serializable types, and then the new graph is serialized.  Similarly, when the GraphML is deserialized, the resulting graph is copied into a new FSM.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I could have avoided creating these extra types and implementing the copy process, but to do so would have cluttered and complicated the overall FSM implementation; XML-serializable properties must be public!  For states, an actual state class is needed containing the start/final state flags (in essence, the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;GraphMLState&lt;/span&gt; class).  Storing start/final state flags on a state class creates a very sparse data set which I wanted to avoid (there is only ever one start state, and generally very few final states), and consequently I chose to maintain the string representation for the state.  For transitions, each delegate needs to be represented as a string implying a new read/write property.  This new property doesn't make sense as it is unnatural for a user to set a delegate/event using a string representation.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;Serializing Delegates (and events)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;TransitionPredicate&lt;/span&gt; property and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;OnStateTransition&lt;/span&gt; event are both delegates, which are difficult to serialize/deserialize to/from XML.  You can't expect a delegate to be serialized using &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx"&gt;XmlSerializer&lt;/a&gt;&lt;/span&gt; becuase an XML-serializable type requires a parameterless constructor.  So to accomplish this, delegate-to-string-to-delegate conversion code is required.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A delegate may reference either a static or instance method, and in order to deserialize an instance method, the serializer needs to reconstruct the object state that owns the method.  In otherwords, the method's parent object needs to be serialized as well.  This does not create a user friendly scenario for creating an FSM via XML, so I prohibited this type of method from being serialized all together.  Binary serialization is better suited for this task, which is a feature that will be implemented in the future.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, for delegate serialization to work, your delegate must reference a static method.  When serialized, it will have the following form: &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;methodName&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;;&lt;/span&gt;assemblyQualifiedDeclaringTypeName&lt;/span&gt;.  An example of a serialized delegate for the [&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;System.Char.IsDigit&lt;/span&gt;] method is: &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;IsDigit;System.Char, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;During deserialization, if the method is discovered to be invalid (i.e. it does not exist, the signature isn't that of a predicate, etc...) then it will be replaced with a default predicate.  The default predicate returns &lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;false&lt;/span&gt; for any input value. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Events pose a challenging conversion task because an event is really a multicast delegate in disguise.  Each method subscribed to the event will need to be validated and serialized as descibed above.  Furthermore, this will be a reflection-heavy task since the delegate is stored in a compiler-generated field.  Currently, I have avoided implementing this feature and will consider its implementation in the future.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-5516052740105407748?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bUVtyRwCdvt2pPkdoCFe7YSx0O4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bUVtyRwCdvt2pPkdoCFe7YSx0O4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bUVtyRwCdvt2pPkdoCFe7YSx0O4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bUVtyRwCdvt2pPkdoCFe7YSx0O4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=FnrheFea9j8:5sgqf6atX3E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=FnrheFea9j8:5sgqf6atX3E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=FnrheFea9j8:5sgqf6atX3E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=FnrheFea9j8:5sgqf6atX3E:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/FnrheFea9j8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/5516052740105407748/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=5516052740105407748" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/5516052740105407748?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/5516052740105407748?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/FnrheFea9j8/graphml-serialization-for-fsms.html" title="GraphML Serialization for FSMs" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/01/graphml-serialization-for-fsms.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQX49fCp7ImA9WxJTE04.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-6197080105326599863</id><published>2009-01-14T13:32:00.000-08:00</published><updated>2009-04-21T10:58:40.064-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-21T10:58:40.064-07:00</app:edited><title>Thinking About XML Documentation Comments</title><content type="html">One of the features for the &lt;a href="http://www.codeplex.com/jolt/Release/ProjectReleases.aspx?ReleaseId=20320"&gt;Jolt 0.2 release&lt;/a&gt; is to add support for &lt;a href="http://www.codeplex.com/jolt/WorkItem/View.aspx?WorkItemId=95"&gt;propagating XML comments&lt;/a&gt; for proxy methods in the Jolt.Testing library.  During the past holiday season, I started to dabble in an implementation and consequently started to research what is required to complete this task.  Ideally, I would like to support a syntax that is depicted as follows.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using System.Xml.Linq;&lt;br /&gt;&lt;br /&gt;void ParseXmlComments(Assembly assembly)&lt;br /&gt;{&lt;br /&gt;XmlDocCommentReader reader = new XmlDocCommentReader(assembly);&lt;br /&gt;XNode[] comments = {&lt;br /&gt; reader.GetComments(assembly.GetType("MyType")),&lt;br /&gt; reader.GetComments(assembly.GetType("OtherType").GetMethod("f")),&lt;br /&gt; reader.GetComments(assembly.GetType("OtherType").GetProperty("g")),&lt;br /&gt; reader.GetComments(assembly.GetType("YetAnotherType").GetConstructor(Type.EmptyTypes))&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;XDocument dom = new XDocument("root", comments);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;The easy part of supporting such an implementation is parsing the XML file so that a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;MemberInfo&lt;/span&gt; or &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Type&lt;/span&gt; object can index a block of XML (the comments).  The rules for doing so are straightforward, and &lt;a href="http://msdn.microsoft.com/en-us/library/fsbx0t7x.aspx"&gt;documented&lt;/a&gt; in the MSDN help system.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The tricky part lies in the first line of psuedo-code: inferring the location of the XML file from an &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Assembly&lt;/span&gt; object.  XML comments are always installed in a directory that is either very near to, or the same as the installation directory for an assembly.  This is done by convention and facilitates the file's location from Visual Studio's Intellisense.  Given that the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Assembly&lt;/span&gt; class offers &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;CodeBase&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Location&lt;/span&gt; properties, it may appear trivial to locate the file.  However these properties do not guarantee finding the &lt;span class="Apple-style-span" style="font-style: italic;"&gt;reference assembly&lt;/span&gt; path for a .NET Framework assembly, which is the path that contains the XML file.  The "&lt;a href="http://msdn.microsoft.com/en-us/magazine/cc188723.aspx"&gt;.NET Matters&lt;/a&gt;" article from MSDN Magazine (June 2004) suggests using &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.runtimeenvironment.getruntimedirectory.aspx"&gt;RuntimeEnvironment.GetRuntimeDirectory()&lt;/a&gt; to locate the reference assembly path, but this fails for .NET 3.0 and .NET 3.5, which use version 2.0 of the common langauge runtime.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Given these issues, I should note that the path inference algorithm using the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;CodeBase&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Location&lt;/span&gt; properties will work for assemblies that are loaded from the same directory as the host application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The following is a summary of my research and conclusions relating to supporting the locating of the XML comments file for an &lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;Assembly&lt;/span&gt; object.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;Reference Assemblies, Location, and CodeBase&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;span class="Apple-style-span" style="font-style: italic;"&gt;reference assemblies&lt;/span&gt; path is the location in which the .NET Framework installer places assemblies (and their XML comments) &lt;span class="Apple-style-span" style=""&gt;prior&lt;/span&gt; to installing the assemblies in the global assembly cache (GAC).  An IDE or compiler will &lt;span class="Apple-style-span" style="font-style: italic;"&gt;reference&lt;/span&gt; the assemblies from this location, while the runtime will generally &lt;span class="Apple-style-span" style="font-style: italic;"&gt;load&lt;/span&gt; assemblies from another location (i.e. the GAC or the local directory of the running application).  Assemblies from .NET 3.0 and onwards are installed to an explicit reference assemblies directory, but are loaded from the GAC.  For previous .NET Framework versions, assemblies are loaded from the path they were installed to.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;span class="Apple-style-span" style="font-style: italic;"&gt;Location&lt;/span&gt; path is the location from which an assembly is loaded.  For the .NET Framework assemblies (any version), this is generally going to be the GAC.  For user assemblies, it could be something else (like the local application folder), and a shadow-copied assembly will yield the shadow-copy path in its Location property.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;span class="Apple-style-span" style="font-style: italic;"&gt;CodeBase&lt;/span&gt; path is the location from which an assembly was first found.  &lt;a href="http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx"&gt;Suzanne Cook&lt;/a&gt; gives the example that this path may be an internet URI for a downloaded assembly.  Furthermore, Cook states that the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;CodeBase&lt;/span&gt; property is not guaranteed to be set for a GAC-loaded assembly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Given these distinctions, it is clear that the reference assemblies path is the ideal path to locate since it will always be the same regardless of how the assembly was obtained or loaded.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;Programmatically Locating the Xml Comments File&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;The CLR has no knowledge of a reference assembly path, so it makes sense that you should not expect a .NET Framework API that knows how to locate the path.  However, during my efforts to find such an API, I came across the MSBuild task &lt;a href="http://msdn.microsoft.com/en-us/library/9ad3f294.aspx"&gt;ResolveAssemblyReference&lt;/a&gt;.  This task will give the physical disk location of the given assembly, the paths to all of its assemlby references, and the paths to any related files.  The related files could be XML, PDB, or any extension that you provide.  &lt;a href="http://blogs.msdn.com/jomo_fisher/archive/2008/05/22/programmatically-resolve-assembly-name-to-full-path-the-same-way-msbuild-does.aspx"&gt;Jomo Fisher&lt;/a&gt; gives an example of using the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.build.tasks.resolveassemblyreference.aspx"&gt;managed API&lt;/a&gt; for this task to resolve assembly references in his F# code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I thought this class would solve my problem, but upon closer inspection of the program output you will notice that the XML files are not found, even for assemblies that share the same directory as their XML files (i.e. System.Core.dll).  I tried different configurations of the class, but with no success. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, in order to locate the XML comments file for a given assembly, I will have to rely on the technique used by &lt;a href="http://www.lutzroeder.com/dotnet/"&gt;Lutz Roeder's Reflector&lt;/a&gt;: search a predefined list of paths, which is expandable with user data.  This has the drawback of needing to update the library each time a new .NET Framework is released (as it may introduce a new reference assembly path), but it is a good short-term fix until I can figure out why the ResolveAssemblyReference class doesn't function as I expect it to.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-6197080105326599863?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bZNhRlCRr_A9opc1utAtXHFQS-s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bZNhRlCRr_A9opc1utAtXHFQS-s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bZNhRlCRr_A9opc1utAtXHFQS-s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bZNhRlCRr_A9opc1utAtXHFQS-s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=1rilBasXzyw:Y7102wI_nSE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=1rilBasXzyw:Y7102wI_nSE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=1rilBasXzyw:Y7102wI_nSE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=1rilBasXzyw:Y7102wI_nSE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/1rilBasXzyw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/6197080105326599863/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=6197080105326599863" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/6197080105326599863?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/6197080105326599863?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/1rilBasXzyw/thinking-about-xml-documentation.html" title="Thinking About XML Documentation Comments" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2009/01/thinking-about-xml-documentation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQDRH84cSp7ImA9WxVTEkk.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-5599544695855895219</id><published>2008-12-25T14:15:00.000-08:00</published><updated>2008-12-25T14:32:55.139-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-25T14:32:55.139-08:00</app:edited><title>Finite State Machine Interface Overview</title><content type="html">Merry Christmas all!&lt;br /&gt;&lt;br /&gt;I've been working on flushing out the interface to the &lt;span style="font-family:courier new;"&gt;FiniteStateMachine&lt;/span&gt; (FSM) class and have reached a point of near-completion; you may review the source code at &lt;a href="http://www.codeplex.com/jolt/SourceControl/changeset/view/17779"&gt;revision 17779&lt;/a&gt;.  The current implementation will let one add states and transitions to an FSM, set/clear an FSM's final state(s), and set/clear an FSM's start state.  State enumeration and input symbol acceptance are also supported, along with an implicit error state.  For examples on how to accomplish these tasks, please review the &lt;a href="http://www.codeplex.com/jolt/Wiki/View.aspx?title=Jolt.FSM"&gt;Jolt FSM documentation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The following diagram shows the public interface of the available classes and their methods (less constructors for brevity).&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://img213.imageshack.us/my.php?image=fsminterfaceft9.png"&gt;&lt;img src="http://img213.imageshack.us/img213/8462/fsminterfaceft9.png" border="0" height="575" width="515" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The methods that are missing from this interface are those to serialize/deserialize the FSM, and those that allow you to export the FSM to a &lt;a href="http://www.codeplex.com/quickgraph"&gt;QuickGraph&lt;/a&gt; data structure.  The latter methods are important because they enable the former, and they also provide access to the transitions and states of the FSM (as edges and vertices, respectively).  Having access to the graph also allows analysis via &lt;a href="http://www.codeplex.com/quickgraph/Wiki/View.aspx?title=Algorithms&amp;amp;referringTitle=User%20Manual"&gt;QuickGraph algorithms&lt;/a&gt;.  Thus, the next work item I will take on will be in adding these missing methods, and also to address the serialization/deserialization issues I brought up in my &lt;a href="http://joltdev.blogspot.com/2008/12/finite-state-machine-first-cut.html"&gt;previous post&lt;/a&gt;.  Some of the work-items that are required for this task are to ensure that transition (edge) labels are created when converting the graph to GLEE, MSAGL, GraphViz, or GraphML, along with making sure a final state is appropriately tagged in the target format.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-5599544695855895219?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/po1dum0CSx7V0P3VAn6p0V15EGU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/po1dum0CSx7V0P3VAn6p0V15EGU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/po1dum0CSx7V0P3VAn6p0V15EGU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/po1dum0CSx7V0P3VAn6p0V15EGU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=saCUiLdG0kk:ZV3xPd-iBpw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=saCUiLdG0kk:ZV3xPd-iBpw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=saCUiLdG0kk:ZV3xPd-iBpw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=saCUiLdG0kk:ZV3xPd-iBpw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/saCUiLdG0kk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/5599544695855895219/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=5599544695855895219" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/5599544695855895219?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/5599544695855895219?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/saCUiLdG0kk/finite-state-machine-interface-overview.html" title="Finite State Machine Interface Overview" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2008/12/finite-state-machine-interface-overview.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEADRno4eCp7ImA9WxJTE04.&quot;"><id>tag:blogger.com,1999:blog-2550103727347014075.post-3547746317169408075</id><published>2008-12-10T13:48:00.000-08:00</published><updated>2009-04-21T10:59:37.430-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-21T10:59:37.430-07:00</app:edited><title>Draft Implementation of the Finite State Machine</title><content type="html">&lt;div&gt;Good day all!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.codeplex.com/jolt/SourceControl/changeset/view/17566"&gt;Revision #17566&lt;/a&gt; contains a &lt;span style="font-style: italic;"&gt;somewhat&lt;/span&gt; usable implementation of the &lt;span style="font-family:courier new;"&gt;FiniteStateMachine&lt;/span&gt; (FSM) class.  I say &lt;span style="font-style: italic;"&gt;somewhat&lt;/span&gt;, because the current class interface and available features are not providing the level of abstractions needed to encapsulate the error-prone tasks of using an FSM.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Overview&lt;/span&gt;&lt;br /&gt;Here is a quick overview of what can be done with the current implementation.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Programmatically add states and transitions to an FSM.&lt;/li&gt;&lt;li&gt;Specify a predicate per transition, denoting which input symbols cause the transition.&lt;/li&gt;&lt;li&gt;Construct an enumerator to walk the FSM, one input symbol at a time.&lt;/li&gt;&lt;/ul&gt;For most cases, one is interested if a collection of input symbols are accepted or rejected by an FSM.  With the current implementation, you would need to feed the symbols to the enumerator one at a time and check the enumerator's return value for failure.  Also, the FSM has no notion of a final state, so the caller of the enumerator has the burden of checking the validity of the resulting state.  All of this is tedious work, and will be encapsulated in the FSM class as part of a future &lt;a href="http://www.codeplex.com/jolt/WorkItem/View.aspx?WorkItemId=3449"&gt;work item&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The following is a code sample that demonstrates the usage of the FSM to validate a Canadian postal code.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;// Validates a Canadian postal code (xnx-nxn, where x is a letter and n is a digit; e.g. H0H-0H0).&lt;br /&gt;bool ValidatePostalCode(string postalCode)&lt;br /&gt;{&lt;br /&gt;  FiniteStateMachine&amp;lt;char&amp;gt; fsm = new FiniteStateMachine&amp;lt;char&amp;gt;;&lt;br /&gt;  fsm.AddState("start");&lt;br /&gt;  fsm.AddState("final");&lt;br /&gt;  fsm.AddState("letter_0");&lt;br /&gt;  fsm.AddState("letter_1");&lt;br /&gt;  fsm.AddState("letter_2");&lt;br /&gt;  fsm.AddState("hyphen");&lt;br /&gt;  fsm.AddState("digit_0");&lt;br /&gt;  fsm.AddState("digit_1");&lt;br /&gt;&lt;br /&gt;  fsm.AddTransition(new Transition&amp;lt;char&amp;gt;("start", "letter_0", Char.IsLetter));&lt;br /&gt;  fsm.AddTransition(new Transition&amp;lt;char&amp;gt;("letter_0", "digit_0", Char.IsDigit));&lt;br /&gt;  fsm.AddTransition(new Transition&amp;lt;char&amp;gt;("digit_0", "letter_1", Char.IsLetter));&lt;br /&gt;  fsm.AddTransition(new Transition&amp;lt;char&amp;gt;("letter_1", "hyphen", ch =&gt; ch == '-'));&lt;br /&gt;  fsm.AddTransition(new Transition&amp;lt;char&amp;gt;("hyphen", "digit_1", Char.IsDigit));&lt;br /&gt;  fsm.AddTransition(new Transition&amp;lt;char&amp;gt;("digit_1", "letter_2", Char.IsLetter));&lt;br /&gt;  fsm.AddTransition(new Transition&amp;lt;char&amp;gt;("letter_2", "final", Char.IsDigit));&lt;br /&gt;&lt;br /&gt;  IFsmEnumerator&amp;lt;char&amp;gt; enumerator = fsm.CreateStateEnumerator("start");&lt;br /&gt;  foreach(char symbol in postalCode)&lt;br /&gt;  {&lt;br /&gt;    if(!enumerator.NextState(symbol)) { return false; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return enumerator.CurrentState == "final";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Overall, a bit laborious but it sets a good foundation to get the internals working.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;QuickGraph and FSM Persistence&lt;/span&gt;&lt;br /&gt;The FSM classes use &lt;a href="http://www.codeplex.com/quickgraph"&gt;QuickGraph&lt;/a&gt; as the underlying storage for the representation of the FSM.  I chose to use this library over the tabular FSM representation because the graph data structure avoids a sparse FSM table, and that the graph library supports graph serialization, persistence, and visualization.  A quick comparison of the two data structures shows that navigation speed of the graph from vertex to vertex is on the same order as a table lookup, however the memory overhead is slightly higher due to the management of hash tables versus a single two-dimensional array.  In the future, I may consider abstracting the data storage of the FSM into a policy to support the tabular implementation.&lt;br /&gt;&lt;br /&gt;I've also been concerned with the ability to serialize and persist a graph that contains dynamic data structures such as anonymous delegates.  How does one represent a non-static method call in XML?  I've verified that the &lt;a href="http://www.codeplex.com/quickgraph/Wiki/View.aspx?title=.NET%20Serialization&amp;amp;referringTitle=User%20Manual"&gt;binary serializer&lt;/a&gt; supports method and parameter serialization, but this doesn't bode well with users that want to manage and create an FSM in a human-readable file.  So, I'm going to revisit this issue when addressing the &lt;a href="http://www.codeplex.com/jolt/WorkItem/View.aspx?WorkItemId=3451"&gt;serialization work item&lt;/a&gt;; the QuickGraph graph &lt;a href="http://www.codeplex.com/quickgraph/Wiki/View.aspx?title=Visualization%20Using%20MsAgl&amp;amp;referringTitle=User%20Manual"&gt;visualizers&lt;/a&gt; may have some native support to address this issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2550103727347014075-3547746317169408075?l=joltdev.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3XMPUdaepwsQvR-guzHnCR4qZbA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3XMPUdaepwsQvR-guzHnCR4qZbA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3XMPUdaepwsQvR-guzHnCR4qZbA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3XMPUdaepwsQvR-guzHnCR4qZbA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Dn_4lNjzXdQ:farRgyiVGi4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Dn_4lNjzXdQ:farRgyiVGi4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?i=Dn_4lNjzXdQ:farRgyiVGi4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?a=Dn_4lNjzXdQ:farRgyiVGi4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/JoltNetDevelopmentBlog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoltNetDevelopmentBlog/~4/Dn_4lNjzXdQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://joltdev.blogspot.com/feeds/3547746317169408075/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2550103727347014075&amp;postID=3547746317169408075" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/3547746317169408075?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2550103727347014075/posts/default/3547746317169408075?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/JoltNetDevelopmentBlog/~3/Dn_4lNjzXdQ/finite-state-machine-first-cut.html" title="Draft Implementation of the Finite State Machine" /><author><name>Steve Guidi</name><uri>http://www.blogger.com/profile/00792115840600367440</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://4.bp.blogspot.com/_tqULVLyl8Mw/SWDfO8VCthI/AAAAAAAACQA/9zf1WJzCdg4/s1600-R/accountze9.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://joltdev.blogspot.com/2008/12/finite-state-machine-first-cut.html</feedburner:origLink></entry></feed>

