<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Nicholas Blumhardt</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/nblumhardt/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/nblumhardt/feed.xml</link>
    <description />
    <lastBuildDate>Wed, 17 Apr 2019 03:24:29 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Back at Microsoft, new blog location...</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/back-at-microsoft-new-blog-location</link>
      <pubDate>Wed, 05 Oct 2011 10:37:51 GMT</pubDate>
      <dc:creator><![CDATA[Nicholas Blumhardt]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2011/10/05/back-at-microsoft-new-blog-location/</guid>
      <description><![CDATA[I've moved back to Redmond and again work on the .NET framework.
I don't currently plan on reviving...]]></description>
      <content:encoded><![CDATA[<p>I've moved back to Redmond and again work on the .NET framework.</p>
<p>I don't currently plan on reviving this blog. You can find me online at <a title="my personal blog" href="https://nblumhardt.com">my personal blog</a> or keep up with our team via <a title="the BCL team blog" href="https://blogs.msdn.com/b/bclteam/">the BCL team blog</a>.</p>
<p>Thanks for dropping by!</p>]]></content:encoded>
    </item>
    <item>
      <title>Homeward Bound</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/homeward-bound</link>
      <pubDate>Tue, 29 Sep 2009 17:01:00 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/09/29/homeward-bound/</guid>
      <description><![CDATA[The last year in Redmond has been truly amazing. Besides working with the great people in the .NET...]]></description>
      <content:encoded><![CDATA[<p align="left">The last year in Redmond has been truly amazing. Besides working with the great people in the .NET team and elsewhere at Microsoft – an experience that can’t be done justice in a brief blog post like this – I’ve also had a chance to take in Seattle and to explore the incredible Pacific Northwest.</p>  <p align="left">It might come as a bit of a surprise then to hear that I’m leaving the US to return to Brisbane, Australia. Despite the many attractions of being here, I’ve found that it is too far to be away from my family and friends.</p>  <p align="left">This Friday will be my last day here, and this blog will shortly be going into ‘read-only’ mode, so please <a mce_href="https://twitter.com/nblumhardt" href="https://twitter.com/nblumhardt">find me on Twitter</a> if you’d like to keep in touch.</p>  <p align="left">Nick</p>]]></content:encoded>
    </item>
    <item>
      <title>Debug Composition from within Visual Studio</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/debug-composition-from-within-visual-studio</link>
      <pubDate>Thu, 24 Sep 2009 15:12:24 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/09/24/debug-composition-from-within-visual-studio/</guid>
      <description><![CDATA[This morning Dave came up with a great suggestion for finding MEF composition problems from within...]]></description>
      <content:encoded><![CDATA[<p>This morning <a href="https://davesbox.com">Dave</a> came up with a great suggestion for finding MEF composition problems from within Visual Studio.</p>  <p>By registering the composition analyzer as an external tool, the <a href="https://blogs.msdn.com/nblumhardt/archive/2009/08/28/analyze-mef-assemblies-from-the-command-line.aspx">root cause of a composition problem</a> can be located in a flash!</p>  <p><strong><em>Step 1 - Obtain MEFX.EXE</em></strong></p>  <p>First, you’ll need to build <strong>mefx.exe</strong> from the <a href="https://mef.codeplex.com/Release/ProjectReleases.aspx">MEF Codeplex Drop</a> (at this time, in the non-Silverlight zip files under /Samples/CompositionDiagnostics).</p>  <p>For demo purposes I’ve placed this (and Microsoft.ComponentModel.Composition.Diagnostics.dll) in C:\Tools.</p>  <p><strong><em>Step 2 – Register MEFX.EXE as an External Tool</em></strong></p>  <p>In Visual Studio, select the <em>Tools &gt; External Tools</em> menu item. This will bring up a dialog like the following:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb.png" width="488" height="486" /></a> </p>  <p>Here you’ll need to click <em>Add</em> and enter the information above. Importantly, select the <em><strong>Use Output Window</strong></em> option.</p>  <p>Note the <em>/causes</em> and <em>/verbose </em>switches. This tells mefx to find parts with missing dependencies that aren’t simply the result of <a href="https://mef.codeplex.com/Wiki/View.aspx?title=Debugging%20and%20Diagnostics">‘cascading’ failures</a>.</p>  <p><strong><em>Step 3 – Run Composition Diagnostics</em></strong></p>  <p>Now that the tooling is set up, finding those composition problems is a breeze!</p>  <p>In my example application, I’m unable to resolve instances of <em>Extensions.Abc</em>:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_10.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_10.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb_4.png" width="238" height="25" /></a> </p>  <p>The exception message tells me that no instances of <em>Abc </em>are available, but I <strong>know</strong> that it is there in my catalog, so something else must be wrong…</p>  <p>In Solution Explorer, I select the executable project:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_8.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb_3.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb_3.png" width="228" height="117" /></a> </p>  <p>Then, under the <em>Tools</em> menu, I click the <em>Debug Composition</em> item that we added in Step 2:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb_1.png" width="442" height="484" /></a> </p>  <p>This will analyze all of the assemblies in the output directory of the application, to find the root cause of the composition failure.</p>  <p><strong>NOTE: Currently, only .DLL files are searched, so parts in .EXE files won’t be included in analysis. In a future version of MEFX this will change, but for now, I recommend keeping all parts in .DLL files.</strong></p>  <p>The output of the tool is piped to the <em>Output</em> window:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_6.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DebugCompositionfromwithinVisualStudio_9913/image_thumb_2.png" width="644" height="219" /></a></p>  <p>Let’s break down this output line-by-line.</p>  <p>First, the name of the problematic part is displayed:</p>  <blockquote>   <p><em>[Part] Extensions.Def from: DirectoryCatalog (Path=&quot;c:\Workspace\ExampleExtensibleApp\Extensions.dll\bin\Debug\&quot;)       <br />&#160; [Primary Rejection]</em></p> </blockquote>  <p>The text <em>Primary Rejection </em>indicates that the analysis identified this as a root cause.</p>  <p>We then see a bit more information about the part, and the status of each of its imports. The problematic import is shown here:</p>  <blockquote>   <p><em>&#160; [Import] Extensions.Def.Ghi (ContractName=&quot;c&quot;)       <br />&#160;&#160;&#160; [Exception] System.ComponentModel.Composition.ImportCardinalityMismatchException: No valid exports were found that match the constraint '(((exportDefinition.ContractName == &quot;c&quot;) AndAlso (exportDefinition.Metadata.ContainsKey(&quot;ExportTypeIdentity&quot;) AndAlso &quot;Extensions.Ghi&quot;.Equals(exportDefinition.Metadata.get_Item(&quot;ExportTypeIdentity&quot;)))) AndAlso ((Not(exportDefinition.Metadata.ContainsKey(&quot;System.ComponentModel.Composition.CreationPolicy&quot;)) OrElse Any.Equals(exportDefinition.Metadata.get_Item(&quot;System.ComponentModel.Composition.CreationPolicy&quot;))) OrElse Shared.Equals(exportDefinition.Metadata.get_Item(&quot;System.ComponentModel.Composition.CreationPolicy&quot;))))', invalid exports may have been rejected.        <br />&#160;&#160; at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition, AtomicComposition atomicComposition)        <br />&#160;&#160; at Microsoft.ComponentModel.Composition.Diagnostics.CompositionInfo.AnalyzeImportDefinition(ExportProvider host, IEnumerable`1 availableParts, ImportDefinition id) in C:\Users\niblumha\Desktop\Microsoft.ComponentModel.Composition.Diagnostics\CompositionInfo.cs:line 157</em></p> </blockquote>  <p>There’s a lot of information here, but the important thing to note is that the import is for property <em>Ghi</em>, which imports contract “<em>c”</em>.</p>  <p>We now know which import in the composition is problematic, and can possibly determine our root cause manually from this information.</p>  <p>More interestingly though, the tool provides some suggestions for fixing this error. Here we’re told that there is a part in the system that <em>looks like</em> it could satisfy the import, but has some problems:</p>  <blockquote>   <p><em>&#160;&#160;&#160; [Unsuitable] Extensions.Ghi (ContractName=&quot;c&quot;) from: Extensions.Ghi from: DirectoryCatalog (Path=&quot;c:\Workspace\ExampleExtensibleApp\Extensions.dll\bin\Debug\&quot;)       <br />&#160;&#160;&#160;&#160;&#160; [Because] TypeIdentity, The export is a 'System.Object', but the import requires 'Extensions.Ghi'. These types must match exactly (conversions are not supported.)        <br />&#160;&#160;&#160;&#160;&#160; [Because] CreationPolicy, The import requires creation policy 'Shared', but the exporting part only supports 'NonShared'.</em></p> </blockquote>  <p></p>  <p>Diagnostics in MEF are a high priority for us. The declarative nature of MEF composition gives us a lot of interesting opportunities for tooling, so expect to see more work along these lines.</p>  <p>As always, feedback is appreciated!</p>]]></content:encoded>
    </item>
    <item>
      <title>Parameterised Triggers and Re-Entrant States in Stateless v2</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/parameterised-triggers-and-re-entrant-states-in-stateless-v2</link>
      <pubDate>Sat, 29 Aug 2009 21:34:51 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/08/29/parameterised-triggers-and-re-entrant-states-in-stateless-v2/</guid>
      <description><![CDATA[Since working on a clinical outcomes review system a couple of years ago, I’ve been aware of the gap...]]></description>
      <content:encoded><![CDATA[<p>Since working on a <em>clinical outcomes review system</em> a couple of years ago, I’ve been aware of the gap between simple hand-coded workflows and the full-blown workflow tools.</p>  <p><a href="https://stateless.googlecode.com">Stateless</a> embodies the idea that a state machine can use closures to <strong>implement workflow without taking on persistence responsibilities</strong>. So long as all of the data used to drive the state machine is external to it, a regular ORM or other persistence mechanism can deal with identity, persistence and transactional issues. This substantially reduces the technical complexity of the framework.</p>  <p>As a ‘fun’ project, I haven’t done much other than maintain the site since the first version was finished. The second version extends the paradigm just a little, but in doing so makes a wider range of scenarios cleanly approachable.</p>  <p>To illustrate the new features I’ll draw on <a href="https://www.odetocode.com/Articles/460.aspx">Scott Allen’s nifty bug tracker example</a> for Windows Workflow.</p>  <h2>Parameterised Triggers</h2>  <p>The triggers that drive transitions in a state machine are approximately analogous to events or commands. Like events and commands, triggers can be associated with parameters.</p>  <ul>   <li>When a bug is <em>assigned</em>, the parameter may be the <em>assignee</em>; </li>    <li>When an order is <em>cancelled</em>, the parameter may be the <em>reason</em>; </li>    <li>etc. </li> </ul>  <p>Modelling these details in Stateless, I adopted the some design goals and constraints:</p>  <ol>   <li>Retain the existing simple syntax for non-parameterised triggers; </li>    <li>Execute parameter-driven logic <em>during</em> the transition, i.e. <em>after</em> the exit events for the last state have fired; </li>    <li>Make it clear to the user exactly when parameter-driven logic will execute; </li>    <li>Control interference between parameter-driven logic and guard conditions; </li>    <li>Ensure parameter type-safety at compile time. </li> </ol>  <h3>New APIs</h3>  <p>To associate parameters with a trigger, <em>StateMachine </em>provides the <em>SetTriggerParameters()</em> generic methods:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_6.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_6.png"><img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="67" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_2.png" width="569" border="0" /></a> </p>  <p><em>SetTriggerParameters() </em>accepts one generic parameter for each of the trigger’s parameters, so in this case the <em>Assign</em> trigger is being associated with a single parameter of type <em>string</em>.</p>  <p>This method is called once, when the state machine is being configured.</p>  <p>The return value in this case is a <em>TriggerWithParameters&lt;string&gt;</em> object that lets us invoke the <em>Fire() </em>method in a strongly-typed way:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_4.png"><img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="28" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_1.png" width="388" border="0" /></a>The C# compiler will use inference to determine that the parameter to the trigger is of type <em>string</em>. Attempting to fire <em>assignTrigger</em> with any other parameters will be rejected at compile-time.</p>  <p>Now, all of this would be fairly pointless if <em>Fire()</em> was the only place that the parameters needed checking. However, the firing of the trigger is only half of the story.</p>  <p>When the machine transitions into the new state, logic based on the trigger parameters will need to run:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_8.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_8.png"><img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="62" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_3.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_3.png" width="544" border="0" /></a>Because <em>assignTrigger</em> is provided to the <em>OnEntryFrom()</em> method, the compiler knows that the provided entry action accepts a single parameter of type <em>string</em>.</p>  <p>Putting everything together behind the facade of a domain object leads to a natural, understandable design:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_10.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_10.png"><img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="73" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_4.png" width="353" border="0" /></a> A more complete example is in the <a href="https://code.google.com/p/stateless/source/browse/#hg/BugTrackerExample">Stateless Mercurial repository</a>.</p>  <h3>Alternatives</h3>  <p>One alternative I considered but later discarded was to parameterise the <em>states</em> rather than the triggers, something that seems to be more established in traditional state machine models. After a good deal of unsuccessful experimentation I concluded that state parameterisation isn’t as useful as the trigger-based version.</p>  <h2>Re-Entrant States</h2>  <p>Stateless encourages you to attach program logic to <em>entry </em>and <em>exit </em>events for the states in your state machine.</p>  <p>One of the edge cases that the bug tracker example reveals is re-initialisation of an already active state. When the bug is assigned, an email might be sent to the assignee. If <em>Assign() </em>is called again, to reassign the bug to someone else, it makes sense to re-initialise the <em>Assigned</em> state by executing the exit actions then executing the entry actions again.</p>  <p>To enable this behaviour for a state, the <em>PermitReentry() </em>method is supplied:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_12.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_12.png"><img title="image" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="82" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb.png" width="536" border="0" /></a></p>  <p>The previous version of Stateless considered a self-transition to be the same as an ignored trigger. Version 2 requires that self-transitions are either explicitly ignored, or configured as re-entrant.</p>  <h2>Next?</h2>  <p>These small additions were actually quite a challenge, but Stateless is still a very small library. One idea I’m toyed with is to use it as a ‘kernel’ for higher-level state machine functionality, e.g. an XML or DSL-driven framework. If you have ideas or requests, feel free to visit the <a href="https://stateless.uservoice.com">UserVoice forum</a>!</p>]]></content:encoded>
    </item>
    <item>
      <title>Analyze MEF Assemblies from the Command Line</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/analyze-mef-assemblies-from-the-command-line</link>
      <pubDate>Fri, 28 Aug 2009 13:45:26 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/08/28/analyze-mef-assemblies-from-the-command-line/</guid>
      <description><![CDATA[In MEF Preview 6 we shipped a sample assembly called...]]></description>
      <content:encoded><![CDATA[<p>In <a href="https://blogs.msdn.com/nblumhardt/archive/2009/07/09/mef-preview-6-available.aspx">MEF Preview 6</a> we shipped a sample assembly called <em>Microsoft.ComponentModel.Composition.Diagnostics</em>, demonstrating the kinds of things that can be determined by (semi-) statically analyzing MEF catalogs.</p>  <p>With <a href="https://mef.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=30259#ReleaseFiles">Preview 7</a> we added a utility that makes use of the diagnostics routines to print information about parts directly from the command-line.</p>  <blockquote>   <p><font size="2" face="Courier New">C:\Users\...\CompositionDiagnostics&gt; <strong>mefx /?</strong></font></p>    <p><font size="2" face="Courier New">&#160; /? </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; Print usage. </font></p>    <p><font size="2" face="Courier New">&#160; /causes </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; List root causes - parts with errors not related to the rejection of other parts. </font></p>    <p><font size="2" face="Courier New">&#160; /dir:C:\MyApp\Parts </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; Specify directories to search for parts. </font></p>    <p><font size="2" face="Courier New">&#160; /exporters:MyContract </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; List exporters of the given contract. </font></p>    <p><font size="2" face="Courier New">&#160; /exports </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; Find exported contracts. </font></p>    <p><font size="2" face="Courier New">&#160; /file:MyParts.dll </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; Specify assemblies to search for parts. </font></p>    <p><font size="2" face="Courier New">&#160; /importers:MyContract </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; List importers of the given contract. </font></p>    <p><font size="2" face="Courier New">&#160; /imports </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; Find imported contracts. </font></p>    <p><font size="2" face="Courier New">&#160; /parts </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; List all parts found in the source assemblies. </font></p>    <p><font size="2" face="Courier New">&#160; /rejected </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; List all rejected parts. </font></p>    <p><font size="2" face="Courier New">&#160; /type:MyNamespace.MyType </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; Print details of the given part type. </font></p>    <p><font size="2" face="Courier New">&#160; /verbose </font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160;&#160;&#160; Print verbose information on each part.</font></p> </blockquote>  <p>The <em><strong>/parts</strong></em> switch list all parts in a composition:</p>  <blockquote>   <p><font size="2" face="Courier New">C:\Users\...\CompositionDiagnostics&gt;<strong> mefx /dir:..\MefStudio /parts</strong></font></p>    <p><font size="2" face="Courier New">Designers.CSharp.Commands</font></p>    <p><font size="2" face="Courier New">Designers.BasicComponentFactory</font></p>    <p><font size="2" face="Courier New">Designers.CSharpFormFactory</font></p>    <p><font size="2" face="Courier New">...</font></p> </blockquote>  <p>While the<em> <strong>/rejected</strong></em> and <em><strong>/causes</strong></em> switches will print information about rejected parts and suspected root causes respectively.</p>  <p>By specifying the<strong> /verbose</strong> switch, detailed information about parts can be retrieved:</p>  <blockquote>   <p><font size="2" face="Courier New">C:\Users\...\CompositionDiagnostics&gt; </font><font size="2" face="Courier New"><strong>mefx /dir:..\MefStudio /type:Designers.BasicComponentFactory /verbose</strong></font></p>    <p><font size="2" face="Courier New">[Part] Designers.BasicComponentFactory from: DirectoryCatalog (Path=&quot;..\MefStudio&quot;)</font></p>    <p><font size="2" face="Courier New">&#160; [Export] Designers.BasicComponentFactory (ContractName=&quot;Contracts.HostSurfaceFactory&quot;)</font></p>    <p><font size="2" face="Courier New">&#160; [Import] Contracts.HostSurfaceFactory.propertyGrid (ContractName=&quot;Contracts.IPropertyGrid&quot;)</font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160; [Actual] ToolWindows.PropertyGridWindow (ContractName=&quot;Contracts.IPropertyGrid&quot;) from: ToolWindows.PropertyGridWindow from: DirectoryCatalog (Path=&quot;..\MefStudio&quot;)</font></p>    <p><font size="2" face="Courier New">&#160; [Import] Contracts.HostSurfaceFactory.Commands (ContractName=&quot;System.Void(Contracts.HostSurface)&quot;)</font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160; [Actual] Designers.CSharp.Commands.Cut (ContractName=&quot;System.Void(Contracts.HostSurface)&quot;) from: Designers.CSharp.Commands from: DirectoryCatalog (Path=&quot;..\MefStudio&quot;)</font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160; [Actual] Designers.CSharp.Commands.Copy (ContractName=&quot;System.Void(Contracts.HostSurface)&quot;) from: Designers.CSharp.Commands from: DirectoryCatalog (Path=&quot;..\MefStudio&quot;)</font></p>    <p><font size="2" face="Courier New">&#160;&#160;&#160; [Actual] Designers.CSharp.Commands.Paste (ContractName=&quot;System.Void(Contracts.HostSurface)&quot;) from: Designers.CSharp.Commands from: DirectoryCatalog (Path=&quot;..\MefStudio&quot;)</font></p> </blockquote>  <p>There are a few more goodies in there for the curious.</p>  <p>It is important to realise that the utility can only analyze MEF assemblies built against a compatible version of MEF; for example, <em>mefx.exe </em>built against the CodePlex drops will not be able to analyze assemblies built against the signed .NET Framework version of MEF, and vice-versa.</p>  <p>We call these “samples” right because they’re for the purpose of our own exploration. Some experience with applying these techniques will hopefully lead to some great production-quality tools in a future milestone.</p>  <p>One particular direction I’d like to venture is towards tooling suitable for continuous integration (CI), for example, a build task capable of validating component status.</p>  <p>If you have ideas for improvement or an opportunity to try <em>mefx</em>, we’d love to hear from you.</p>]]></content:encoded>
    </item>
    <item>
      <title>Dynamic Part Instantiation in MEF</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/dynamic-part-instantiation-in-mef</link>
      <pubDate>Thu, 27 Aug 2009 20:57:25 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/08/27/dynamic-part-instantiation-in-mef/</guid>
      <description><![CDATA[Disclaimer: This functionality is not shipping in .NET 4 (but is available in the recent CodePlex...]]></description>
      <content:encoded><![CDATA[<p><em><strong>Disclaimer: </strong>This functionality is <strong>not</strong> shipping in .NET 4 (but is available in the <a href="https://codeplex.com/mef">recent CodePlex drops</a>, see below for more details.)</em></p>  <p>The golden rule of using composition to simplify your architecture is to <a href="https://blogs.msdn.com/nblumhardt/archive/2008/12/27/container-managed-application-design-prelude-where-does-the-container-belong.aspx">avoid calling the container directly</a>.</p>  <p>Until now, MEF users have had to jump through hoops to observe this rule in some circumstances. The most common of these is dynamic part creation – creating instances of parts on-the-fly in response to application events.</p>  <p>To alleviate this, the latest <strong>Silverlight version of MEF</strong> in “Preview 7” introduces a<em> </em><a href="https://blogs.msdn.com/nblumhardt/archive/2009/01/04/declarative-context-adapters.aspx"><em>Declarative Context Adapter</em></a><em> </em>called <em>PartCreator&lt;T&gt;</em>. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_12.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_12.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_5.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_5.png" width="557" height="337" /></a> </p>  <h3>PartCreator&lt;T&gt;</h3>  <p>Imagine we’re writing a pluggable text editor. The application uses a part to represent the document being edited:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb.png" width="309" height="127" /></a> Whenever the user clicks the ‘New’ button, the editor window creates a new instance:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_4.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_1.png" width="381" height="286" /></a> There are a few important things to notice here:</p>  <ul>   <li>Every time <em>OnNewDocument()</em> executes, a new instance supporting <em>IDocument</em> is created (in this case the actual object will be of type <em>TextDocument,</em>) </li>    <li>When MEF sees an <em>[Import]</em> attribute on a member of type <em>PartCreator&lt;T&gt;</em>, it will use the same rules as for <em>Lazy&lt;T&gt; </em>to determine the appropriate contract, </li>    <li>The parameter <em>T</em> is the type of the exported value, not the type of the underlying part implementation, </li>    <li>The return value from <em>CreatePart()</em> is a wrapper class, <em>PartLifetimeContext&lt;T&gt;</em>, that implements IDisposable and must be used to clean up the part when it is no longer required, </li>    <li><em>PartLifetimeContext&lt;T&gt; </em>has a property <em>Value</em> of type <em>T</em>, in this case <em>T</em> will be <em>IDocument</em>. </li> </ul>  <p>MEF supports <em>PartCreator&lt;T&gt;</em> implicitly, in a very similar way to <em>Lazy&lt;T&gt;.</em> There is no additional code required to get this behaviour.</p>  <h3>PartCreator&lt;T, TMetadata&gt;</h3>  <p>Many scenarios for dynamic instantiation need to select the appropriate part to instantiate from several different implementations.</p>  <p>In this example, imagine we’re building a simple MVC web framework (don’t confuse this with ASP.NET MVC; this is just a made-up exercise, not a serious MVC framework design.)</p>  <p>Developers create controllers to handle the various URLs that the web application responds to. Each controller exports the <em>IController</em> contract, and adds some <a href="https://mef.codeplex.com/Wiki/View.aspx?title=Exports%20and%20Metadata">metadata</a> describing the route that the controller handles.</p>  <p>Here’s part of the controller for the <em>/home </em>page:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_6.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_6.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_2.png" width="336" height="128" /></a> Down in the plumbing of our MVC framework, the request handler is going to have to decide which of the available controllers will be invoked by an incoming request.</p>  <p>To do this, the <em>RequestHandler </em>part imports an array of <em>PartCreator&lt;IController, IControllerMetadata&gt;</em>.</p>  <p>When a request comes in (see the <em>HandleRequest() </em>method) the appropriate part creator is chosen and used to create a controller:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_8.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_8.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_3.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_3.png" width="528" height="441" /></a> Notice that the <em>controller</em> variable is used in a <em>using </em>block. This ensures that the controller and any other resources that were used to construct it will be cleaned up after the request is handled.</p>  <h3>Emulating PartCreator&lt;T&gt; on .NET 4</h3>  <p><em>PartCreator&lt;T&gt; </em>is not included in the .NET 4 builds of MEF – it was developed as part of the Silverlight MEF support (where <em>CompositionContainer</em> is much less accessible.) However, with a little work it is possible to emulate some of the <em>PartCreator&lt;T&gt; </em>functionality.</p>  <p>Included with the .NET beta-compatible version of MEF is a sample that supports a limited subset of the feature, under <em>Microsoft.ComponentModel.Composition.DynamicInstantiation</em>.</p>  <p>This assembly includes versions of the part creator types, and an <em>ExportProvider</em> that handles requests for <em>PartCreator&lt;T&gt;</em> when added to the container.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_10.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_10.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/DynamicPartCreationinMEF_BFC9/image_thumb_4.png" width="572" height="76" /></a></p>  <p>This sample doesn’t fully support all container features, and (as you can tell by the lack of unit tests) may blow up in unexpected ways. Instantiation performance is also not guaranteed, thanks to O(n^2) time complexity on the number of exporters of the contract being instantiated.</p>  <p>We’re including this so that .NET 4 users can experiment with the part creator APIs; it is not yet recommended for production use.</p>]]></content:encoded>
    </item>
    <item>
      <title>Implementing Optional Exports with MEF Stable Composition</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/implementing-optional-exports-with-mef-stable-composition</link>
      <pubDate>Fri, 17 Jul 2009 13:59:29 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/07/17/implementing-optional-exports-with-mef-stable-composition/</guid>
      <description><![CDATA[Disclaimer: As usual, this blog post is discussing pre-release software, which may differ from the...]]></description>
      <content:encoded><![CDATA[<p><em><strong>Disclaimer: </strong>As usual, this blog post is discussing pre-release software, which may differ from the final released version.</em></p>  <p><a href="https://ayende.com/Blog/archive/2008/09/25/the-managed-extensibility-framework.aspx">Ayende once observed</a> that <a href="https://codeplex.com/mef">MEF</a> is very focused on dependency management. It’s an accurate description of the driving force that has shaped MEF as it is today.</p>  <p>Dependency management doesn’t end at build time with assembly references. Functional dependencies are more complex and harder to control than static compilation unit dependencies. MEF has some nifty tricks up its sleeve to help out with this task.</p>  <p>Imagine the example of a retail management system:</p>  <table border="1" cellspacing="0" cellpadding="2" width="399"><tbody>     <tr>       <td valign="top" width="101"><strong></strong></td>        <td valign="top" width="99">         <p align="center"><strong>Standard</strong></p>       </td>        <td valign="top" width="98">         <p align="center"><strong>Pro Service</strong></p>       </td>        <td valign="top" width="99">         <p align="center"><strong>Platinum</strong></p>       </td>     </tr>      <tr>       <td valign="top" width="101"><strong>Service Schedule</strong></td>        <td valign="top" width="99">         <p align="center"><strong>&#160;</strong></p>       </td>        <td valign="top" width="98">         <p align="center"><strong>X</strong></p>       </td>        <td valign="top" width="99">         <p align="center"><strong>X</strong></p>       </td>     </tr>      <tr>       <td valign="top" width="101"><strong>Stock Control</strong></td>        <td valign="top" width="99">         <p align="center"><strong>X</strong></p>       </td>        <td valign="top" width="98">         <p align="center"><strong>&#160;</strong></p>       </td>        <td valign="top" width="99">         <p align="center"><strong>X</strong></p>       </td>     </tr>      <tr>       <td valign="top" width="101"><strong>Client List</strong></td>        <td valign="top" width="99">         <p align="center"><strong>&#160;</strong></p>       </td>        <td valign="top" width="98">         <p align="center"><strong>X</strong></p>       </td>        <td valign="top" width="99">         <p align="center"><strong>X</strong></p>       </td>     </tr>      <tr>       <td valign="top" width="101"><strong>Marketing</strong></td>        <td valign="top" width="99"><strong>&#160;</strong></td>        <td valign="top" width="98"><strong>&#160;</strong></td>        <td valign="top" width="100">         <p align="center"><strong>X</strong></p>       </td>     </tr>   </tbody></table>  <p>The <em>AdventureWorks Store Manager </em>application has many features. To support pay-for-play licensing, the company sells several versions (‘SKUs’) targeting different market segments, with different features enabled.</p>  <p>All of these versions are subsets of the same essential codebase. Each SKU, or configuration, includes the relevant pieces.</p>  <h3>Mapping Features to Components</h3>  <p>The implementation of each feature can involve more than one component. Part of the system might look like:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_1.png" width="394" height="329" /></a> A quick description:</p>  <ul>   <li><em>PointOfSale</em> lets a storeperson process sales</li>    <li><em>PointOfSale</em> uses a collection of <em>ItemLookup</em>s representing each kind of thing that can be sold</li>    <li><em>ProductLookup</em> provides <em>ItemLookup</em> functionality for products, and requires exactly one <em>ProductRepository</em> to do its job</li>    <li><em>ServiceLookup</em> is like <em>ProductLookup</em> but for services that may be performed for the client</li> </ul>  <p>An important aspect of the diagram is the cardinality of the relationships.</p>  <p><em>PointOfSale’</em>s one-to-many dependency on <em>ItemLookup</em> is a MEF <em>[ImportMany]</em>:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_6.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_2.png" width="456" height="140" /></a> </p>  <p>The one-to-one dependency between <em>ProductLookup </em>and <em>ProductRepository</em> correspond to MEF required imports. The same applies to <em>ServiceLookup </em>and <em>ServiceRepository</em>:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_8.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_8.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_3.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_3.png" width="458" height="137" /></a> To configure the system, we need to make sure that <em>ServiceLookup </em>doesn’t appear in <em>PointOfSale.ItemLookups </em>when we’re in the “Standard” SKU.</p>  <h3>Partitioning the System</h3>  <p>‘Classic’ approaches to sub-setting used to revolve around conditional compilation (<em>#ifdef</em>s) or runtime <em>“IsEnabled”</em> checks. While effective, the results of these methods can be very difficult to maintain.</p>  <p>Plug-in systems, or selective registration of components in an IoC container, provide a more intentional, centralized way of managing the contents of a SKU.</p>  <p>Even here there is significant complexity and thus room for improvement. Functional dependencies usually span layers and revolve around multiple pieces of code. Some components will appear in multiple SKUs, while others will be available with different degrees of functionality.</p>  <p><em>(Note that we ignore assembly-level partitioning here since market-driven functional partitioning does not always match architecture-driven partitioning.)</em></p>  <h3>Enter Stable Composition</h3>  <p>Tucked away in the recent <a href="https://blogs.msdn.com/nblumhardt/archive/2009/07/09/mef-preview-6-available.aspx">announcement of MEF preview 6</a> was a snippet on what we’ve been calling <em>Stable Composition</em>.</p>  <p>The cornerstone rule of Stable Composition is:</p>  <blockquote>   <p>Parts that have missing <em>required</em> dependencies are ‘rejected.’ They appear in the catalog, but the container never uses them.</p> </blockquote>  <p>Now, the impact this has on a system as a whole is more interesting than it would first appear. Not only will parts with missing dependencies be rejected, but so will any parts that transitively depend on rejected parts. One missing dependency can cause a whole graph of components to be ignored.</p>  <p>This isn’t accidental:</p>  <p><strong>Utilising Stable Composition, one can manage just the parts that <em>define</em> a SKU, and MEF will make sure that dependent parts are included or excluded as needed.</strong></p>  <p>Instead of tracking dependency relationships manually to create a master set of components for each SKU, offload this responsibility to MEF.</p>  <h3>Configuring <em>AdventureWorks Store Manager Standard </em>SKU</h3>  <p>This SKU is characterised by the absence of service-related functionality.</p>  <p>Instead of analyzing all components to determine whether they play a part in service-related scenarios, we make the observation that all such functionality depends on the presence of a <em>ServiceRepository</em>.</p>  <p>When the MEF <em>ComposablePartCatalog </em>is being configured, excluding the <em>ServiceRepository</em> gives us the result we require.</p>  <p>MEF itself will determine which other components depend on the missing functionality and automatically ignore (‘reject’) them:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_10.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_10.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_4.png" width="555" height="330" /></a>This behaviour comes out-of-the-box with MEF – there is no need to opt-in or change the way that the <em>CompositionContainer</em> is used.</p>  <h4>Single Required Dependencies Only</h4>  <p>Rejection typically applies to one-to-one dependencies. The <em>ServiceLookup</em> screen is rejected because it requires exactly one <em>ServiceRepository</em>, and by excluding it from the SKU we’ve effectively disabled the <em>ServiceLookup </em>screen.</p>  <p>The <em>PointOfSale</em> screen’s dependency on many <em>ItemLookup</em>s will never cause it to be rejected, since it can effectively function when the number of available <em>ItemLookup</em>s is zero.</p>  <p>The other common MEF dependency, represented by an import with <em>AllowDefault=true</em>, is an optional dependency. Since by declaring an optional dependency, a component guarantees that it can operate without the dependency present, optional dependencies do not trigger rejection either.</p>  <p>The special case to look out for is when too many implementations are present, e.g. two <em>ServiceRepository</em>s. In this scenario components that depend on a single instance <em>will </em>be rejected.</p>  <h3>Debugging and Testing</h3>  <p>The last drop of MEF included a sample (<em>Microsoft.ComponentModel.Composition.Diagnostics</em>) capable of determining the rejection status of a part. This is useful for debugging at development time, but there’s also an opportunity to do integration-time testing of SKU configurations.</p>  <p>For example, if I’m testing the “Pro Service” SKU and expect <em>ServiceLookup </em>to be available, I might write:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_12.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_12.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_5.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/LightuporMEFOptionalExports_AA58/image_thumb_5.png" width="459" height="188" /></a> </p>  <p>Now, this is a hypothetical test case; I haven’t had an opportunity to use this in anger. It is an interesting possibility though, and worth exploring if you’re going to make heavy use of Stable Composition.</p>  <h3>Optional Exports</h3>  <p>Why did the title of this post include the term ‘Optional Exports*’? This is a useful way to think about how rejection works. MEF components provide exports that are optional, on the condition that their mandatory imports can be satisfied. The <em>ServiceLookup </em>component provides its exports on the condition that <em>ServiceRepository </em>is available.</p>  <p>You can use this way of looking at the feature to implement some other nifty tricks in the realm of ‘light up,’ but that is for another day!</p>  <p><em>(*One of the many subtle coinages of Blake Stone – Blake, where’s your blog?)</em></p>]]></content:encoded>
    </item>
    <item>
      <title>MEF Preview 6 Available</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/mef-preview-6-available</link>
      <pubDate>Thu, 09 Jul 2009 12:29:00 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/07/09/mef-preview-6-available/</guid>
      <description><![CDATA[In the three months that have passed since the last release, we’ve been very busy making final...]]></description>
      <content:encoded><![CDATA[<P mce_keep="true">In the three months that have passed since the last release, we’ve been very busy making final adjustments to get closer to RTM.</P>
<P>In this post I’ve summarized the biggest changes between the Preview 5 and Preview 6 releases.</P>
<P>The highlights are:</P>
<UL>
<LI>Silverlight support</LI>
<LI><STRONG>Lazy&lt;T&gt;</STRONG> replaces <STRONG>Export&lt;T&gt;</STRONG> </LI>
<LI>Collection import changes </LI>
<LI>Inheritance changes </LI>
<LI>Export attribute is unsealed </LI>
<LI><EM>Stable Composition </EM>makes its debut </LI></UL>
<P>You can download MEF Preview 6 from <A href="https://mef.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=30098" mce_href="https://mef.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=30098">the CodePlex site</A>.</P>
<H2>Silverlight Support</H2>
<P>With this release comes an early preview of our Silverlight plans. The included solution <EM>MEFSL.sln</EM> can be used to build MEF binaries that target the newly-released <A href="https://microsoft.com/silverlight" mce_href="https://microsoft.com/silverlight">Silverlight 3</A>.</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image11.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image11.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image11.png"><IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; MARGIN-LEFT: 0px; BORDER-TOP: 0px; MARGIN-RIGHT: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image align=right src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image11_thumb.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image11_thumb.png" width=244 height=223 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image11_thumb.png"></A></P>
<P>Those familiar with the full-framework MEF won’t see many differences in the Silverlight build as it stands today. We aim to have some exciting new features in the eventual release, but for now the APIs are the same apart from changes required because of the different environment.</P>
<H3>Silverlight Catalog</H3>
<P><STRONG>DirectoryCatalog</STRONG> is not available in the Silverlight version. Instead, this is replaced by <STRONG>PackageCatalog</STRONG>.</P>
<P>This API is tentative and will very probably change in a future preview.</P>
<H3>Silverlight Picture Viewer</H3>
<P>There’s a new sample called <EM>PictureViewer</EM> that demonstrates some aspects composition in a Silverlight application.</P>
<H2>Lazy&lt;T&gt;</H2>
<P>One of the first things you’ll notice when moving to the new build is that the <STRONG>System.ComponentModel.Composition.Export&lt;T&gt;</STRONG> and <STRONG>Export&lt;T, TMetadata&gt;</STRONG> types are gone.</P>
<P>In their place, MEF now recognizes the <STRONG>System.Lazy&lt;T&gt;</STRONG> and <STRONG>Lazy&lt;T, TMetadta&gt;</STRONG> types.</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_18.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_18.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_18.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_8.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_8.png" width=346 height=46 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_8.png"></A></P>
<P>Functionally these types match the old ones, however:</P>
<UL>
<LI>The <STRONG>GetExportedObject()</STRONG> method is replaced by a <STRONG>Value</STRONG> property </LI>
<LI>The raw metadata dictionary is gone (if you truly require this, you can use the <STRONG>IDictionary&lt;string, object&gt;</STRONG> type as a metadata view interface) </LI></UL>
<H2>Collection Import Changes</H2>
<P>The <STRONG>System.ComponentModel.Composition.</STRONG><STRONG>ExportCollection&lt;T&gt; </STRONG>type has also been removed. In its place, use <STRONG>IEnumerable&lt;Lazy&lt;T&gt;&gt;</STRONG>, or <STRONG>Lazy&lt;T&gt;[]</STRONG>.</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_20.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_20.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_20.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_9.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_9.png" width=461 height=46 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_9.png"></A>&nbsp;<STRONG>ImportManyAttribute</STRONG> is now required for <EM>all</EM> collection imports.</P>
<H2>Inheritance Changes</H2>
<P><STRONG>PartExportsInheritedAttribute </STRONG>has been removed. The new mechanism separates inheritable exports from non-inheritable exports.</P>
<P>Exports declared using the <STRONG>ExportAttribute </STRONG>are never inherited.</P>
<P>Exports declared using the <STRONG>InheritedExportAttribute</STRONG> will be exposed by sub-classes of the part type.</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_22.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_22.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_22.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_10.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_10.png" width=289 height=198 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_10.png"></A> </P>
<H2>Custom Export Attributes</H2>
<P>In previous releases, <STRONG>ExportAttribute </STRONG>was sealed.</P>
<P>It is now possible to subclass <STRONG>ExportAttribute</STRONG>, and this can be combined with the existing <STRONG>MetadataAttribute </STRONG>functionality.</P>
<P>This means that instead of:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_12.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_12.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_12.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_5.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_5.png" width=375 height=157 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_5.png"></A></P>
<P>It is possible to define a custom attribute that completely describes the export:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_14.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_14.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_14.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_6.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_6.png" width=568 height=269 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_6.png"></A>Thus users can declare both the exported contract and its metadata using only one attribute:</P>
<P>&nbsp;<A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_16.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_16.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_16.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_7.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_7.png" width=396 height=114 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_7.png"></A>We expect this will be very useful for authors of extensible frameworks. </P>
<P><B>Note:</B> We have also unsealed <STRONG>ImportAttribute</STRONG>, <STRONG>ImportManyAttribute</STRONG> and <STRONG>ImportingConstructor</STRONG> thus allowing these to be extended as well.</P>
<H2>Stable Composition</H2>
<P>As an extensibility framework, it is important that MEF applications start and execute reliably even when some extensions lack required dependencies.</P>
<P>Stable Composition contributes to this goal by validating dependencies in advance.</P>
<H3>Part Definition Rejection</H3>
<P>In earlier releases, MEF would hand out lazy exports from parts with missing dependencies. Later, when the export was used an exception would be thrown because of problems creating the part.</P>
<P>There were two major issues with this:</P>
<UL>
<LI>Side-effects of failures during composition could not always be cleaned up </LI>
<LI>Light-up could only be supported via optional dependencies, which led to awkward component designs </LI></UL>
<P>The solution to this problem is:</P>
<P><STRONG><EM>Parts that have missing <U>required</U> dependencies are ‘rejected.’ They appear in the catalog, but the container never uses them.</EM></STRONG></P>
<P>MEF remains dynamic – as parts are added and removed from the composition, the state of part definitions can change. Parts that may have been rejected will become available when their dependencies can be satisfied.</P>
<H3>Atomic Changes</H3>
<P>The container now treats lazy references as <EM>promises</EM>. Once the container hands out a <STRONG>Lazy&lt;T&gt;</STRONG> export, the value is guaranteed to be available, and to remain available for the life of the part that imports it.</P>
<P>The parts available in a MEF container can change, either by adding or removing to the a <STRONG>ComposablePartCatalog</STRONG>, or directly via <STRONG>CompositionContainer.ComposeBatch().</STRONG></P>
<P>In order to keep promises, changes like these are examined carefully and verified not to break anything already instantiated.</P>
<P>If such a change would cause an existing promise to be broken, the change is rejected by means of a <STRONG>CompositionException</STRONG>.</P>
<H3>Diagnosing Composition Problems</H3>
<P>One of the implications of Stable Composition is that the rejected parts will simply never show up.</P>
<P>Because parts are interdependent, one broken part can cause a chain of other dependent parts to be rejected as well.</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_2.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_2.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb.png" width=542 height=320 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb.png"></A> </P>
<P>Finding the root cause of a ‘cascading rejection’ like this can be tricky.</P>
<P>Included in the samples under <EM>/Samples/CompositionDiagnostics </EM>is a prototype diagnostic library that can be used to track composition problems down.</P>
<P>The two basic functions that are implemented allow the rejection state of a part to be inspected, and the contents of an entire catalog to be dumped along with status and root cause analysis information.</P>
<H4>Dump Composition State</H4>
<P>For comprehensive diagnostics, the complete composition can be dumped in text format:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_4.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_4.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_1.png" width=407 height=101 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_1.png"></A> </P>
<P>The output contains many interesting things, including ‘primary rejection’ guesses and analysis of common problems like mismatched type identity, mismatched creation policy, and missing required metadata:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_6.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_6.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_6.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_2.png" width=573 height=691 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_2.png"></A> </P>
<P>There’s enough information here to correctly diagnose most common issues.</P>
<H4>Find Likely Root Causes</H4>
<P>The dump technique above is comprehensive but verbose, and if you have access to the running process in a debugger, the following is more likely to be convenient:</P>
<P><A href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_8.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_8.png" mce_href="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_8.png"><IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_3.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_3.png" width=382 height=30 mce_src="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/MEFforSilverlightAvailableNow_90D1/image_thumb_3.png"></A> </P>
<P>The return value of <STRONG>CompositionInfo.GetPartDefinitionInfo()</STRONG> is an object that gives quick access to all of the same analytical information as the text dump, but relating to the part Foo. The API exposes:</P>
<UL>
<LI>The part’s rejection state (<STRONG>IsRejected</STRONG>) </LI>
<LI>Whether it is a primary cause of rejection, or if it is rejected because of other cascading rejections (<STRONG>IsPrimaryRejection</STRONG>) </LI>
<LI>Which parts are likely to be the root causes of the part’s rejection (<STRONG>PossibleRootCauses</STRONG>) </LI>
<LI>The state of all imports (<STRONG>ImportDefinitions</STRONG>) </LI>
<LI>For each import, which exports would satisfy the imports (<STRONG>ImportDefinitions..Actuals</STRONG>) </LI>
<LI>For each import, which other exports with the same contract name were not matched, and the reason for each (<STRONG>ImportDefinitions..UnsuitableExportDefinitions</STRONG>) </LI></UL>
<H3>Implementing Export Providers</H3>
<P>The <STRONG>ExportProvider.GetExportsCore()</STRONG> method has gained a parameter to support Stable Composition. <STRONG>ExportProvider</STRONG> also has a new event <STRONG>ExportsChanging</STRONG> for the same purpose.</P>
<P>Simple <STRONG>ExportProviders</STRONG> that hand out the same values and do not recursively call into the container can ignore the parameter and event.</P>
<P>If you implement a custom <STRONG>ExportProvider</STRONG> that recursively calls into the container to satisfy dependencies of the exports it hands out, then you should participate in Stable Composition.</P>
<P>Likewise, if the set of available exports in an <STRONG>ExportProvider</STRONG> can change, you’ll need to fire the <STRONG>ExportsChanging</STRONG> and <STRONG>ExportsChanged</STRONG> events.</P>
<P>See the API documentation for these types for more details.</P>
<H2>Other API Changes</H2>
<P>A number of other supporting API changes have been made, and a few obsolete or problematic items removed:</P>
<UL>
<LI><STRONG>CompositionContainer.GetExported<EM>Object</EM>() </STRONG>and related overloads have been renamed to <STRONG>GetExported<EM>Value</EM>()</STRONG> </LI>
<LI><STRONG>CompositionEngine </STRONG>has been renamed <STRONG>ImportEngine</STRONG> </LI>
<LI><STRONG>AttributedModelServices</STRONG> 
<UL>
<LI><STRONG>AddExportedObject&lt;T&gt;()</STRONG> renamed to <STRONG>AddExportedValue&lt;T&gt;()</STRONG> </LI>
<LI><STRONG>ComposeExportedObject&lt;T&gt;()</STRONG> renamed to<STRONG> ComposeExportedValue&lt;T&gt;()</STRONG> </LI>
<LI>New <STRONG>GetMetadataView&lt;TMetadataView&gt;()</STRONG> method </LI>
<LI>New <STRONG>SatisfyIImportsOnce</STRONG>() method </LI></UL></LI>
<LI><STRONG>ICompositionService</STRONG> changes 
<UL>
<LI><STRONG>SatisfyImports()</STRONG> renamed&nbsp; <STRONG>SatisfyImportsOnce()</STRONG> and no longer registers the part for recomposition </LI>
<LI><STRONG>UnregisterForRecomposition() </STRONG>removed </LI>
<LI><STRONG>CompositionServiceExtensions</STRONG> removed </LI></UL></LI>
<LI><STRONG>ContractTypeAttribute</STRONG> removed since exports on interfaces are now inherited </LI>
<LI><STRONG>ComposablePartCatalogChangedEventArgs</STRONG> renamed to <STRONG>ComposablePartCatalogChangeEventArgs</STRONG> </LI>
<LI>New <STRONG>AtomicComposition</STRONG> class supports Stable Composition </LI>
<LI>Contract adapters have been removed </LI></UL>
<H2>Help and Feedback</H2>
<P>Enjoy the new release, and remember that the <A href="https://mef.codeplex.com/Thread/List.aspx" mce_href="https://mef.codeplex.com/Thread/List.aspx">MEF discussion forum</A> on CodePlex is a great place to get help if you find yourself stuck.</P>
<P>The MEF Team is very grateful to everyone who’s provided feedback and input into the new release. I hope we’ve hit the right note, but as always your comments are welcome.</P>]]></content:encoded>
    </item>
    <item>
      <title>Appearance on .NET Rocks!</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/appearance-on-net-rocks</link>
      <pubDate>Fri, 29 May 2009 13:55:00 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/05/29/appearance-on-net-rocks/</guid>
      <description><![CDATA[This week I took some time out to talk to Richard and Carl on .NET Rocks! about Autofac, MEF and...]]></description>
      <content:encoded><![CDATA[<P>This week I took some time out to talk to Richard and Carl on <EM><A href="https://dotnetrocks.com/" mce_href="https://dotnetrocks.com">.NET Rocks!</A></EM> about <A href="https://www.dotnetrocks.com/default.aspx?showNum=450" mce_href="https://www.dotnetrocks.com/default.aspx?showNum=450">Autofac, MEF and component-oriented software</A> in general.</P>
<P>If you have any questions about material from the show, please feel free to post them in the comments.</P>]]></content:encoded>
    </item>
    <item>
      <title>State Machines in Domain Models</title>
      <link>https://docs.microsoft.com/archive/blogs/nblumhardt/state-machines-in-domain-models</link>
      <pubDate>Thu, 16 Apr 2009 02:52:37 GMT</pubDate>
      <dc:creator><![CDATA[niblumha]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/nblumhardt/2009/04/16/state-machines-in-domain-models/</guid>
      <description><![CDATA[I was reminded today of Stateless, a little project that I’m quite fond of.  Stateless is a...]]></description>
      <content:encoded><![CDATA[<p>I was reminded today of <a href="https://stateless.googlecode.com">Stateless</a>, a little project that I’m quite fond of.</p>  <p>Stateless is a <em>hierarchical state machine framework</em> based on <a href="https://codeplex.com/simplestatemachine">Simple State Machine</a> for <a href="https://boo.codehaus.org">Boo</a>, but configured using C# 3.0.</p>  <p>When I <a href="https://ubik.com.au/article/named/stateless">announced Stateless last year</a>, I hardly even explained its purpose, let alone its tongue-in-cheek name. I think I owe it a better start in life!</p>  <p>If you’re doing heavy duty state-machine based programming (writing parsers, radiotherapy machines or flight control systems) then Stateless is probably not what you’re looking for.</p>  <p>If you’re doing domain-driven design, and anxious about the ugly nested ‘if’ and ‘switch’ statements building up around _state variables, Stateless can help.</p>  <p>State-based behaviour is awkward because despite careful programming, it is difficult to see how the states relate to each other. Adding and removing states is error-prone, repetition creeps in, and refactoring gets tricky.</p>  <p>There’s more than one way out. The <a href="https://en.wikipedia.org/wiki/State_pattern">State</a> <a href="https://codebetter.com/blogs/jeremy.miller/archive/2006/04/30/143733.aspx">pattern</a> can be one very elegant solution. </p>  <p>Another solution that works nicely is to create a declarative model of the states, transitions and associated actions, and have a state machine framework ‘run’ it for you. This is the approach enabled by Stateless.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_2.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="551" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb.png" width="337" border="0" /></a> </p>  <p>The Telephone Call state chart is broken down into the following states and triggers:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_4.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="351" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_1.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_1.png" width="238" border="0" /></a> </p>  <p>You can use any types to represent states and triggers, but enumerations are convenient.</p>  <p>After creating an instance of <em>StateMachine</em>, each state is configured independently. Configuration for a state revolves around the triggers that the state can accept, the transitions that these triggers will cause (to new states) and the actions that will be performed when entering or leaving a state.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_6.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_6.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="385" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_2.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_2.png" width="546" border="0" /></a> </p>  <p>Once the state machine has been configured, the triggers can be ‘fired’. The side-effects from firing triggers drive the program.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_8.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_8.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="46" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_3.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_3.png" width="300" border="0" /></a> </p>  <p>You might wonder how this fits into a domain model. <em>StateMachine</em> certainly doesn’t belong on the public surface area of your domain model classes. It’s an implementation detail – like, for example, <em>StringBuilder </em>or <em>Regex.</em></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_10.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_10.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="281" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_4.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_4.png" width="438" border="0" /></a> </p>  <p>Users of the class interact with the state machine indirectly, by calling public methods on the domain object.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_12.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_12.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="178" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_5.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_5.png" width="349" border="0" /></a> </p>  <p>The state machine is configured to call two methods when entering and leaving the Connected state (see the configuration above.)</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_14.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_14.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="197" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_6.png" original-url="https://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_6.png" width="452" border="0" /></a> </p>  <p>Stateless does all of the heavy lifting. For example, the state machine understands that because <em>OnHold</em> is a sub-state of <em>Connected</em>, the <em>Connected </em>entry/exit actions aren’t called when moving <em>between</em> these two states.</p>  <p>Now for a justification of the silly name…</p>  <p>Notice the way that the <em>_state</em> field belongs to the <em>PhoneCall </em>object, rather than the state machine? This allows the field to be easily mapped to a database column by NHibernate or your ORM of choice. The state machine reads and writes the <em>_state</em> value using the pair of lambdas provided to its constructor. In that sense you can <em>almost </em>say that the state machine itself is ‘stateless’. Almost.</p>  <p>There’s some more basic documentation and a source download <a href="https://code.google.com/p/stateless/">at the site</a>. I hope you’ll try Stateless and be pleasantly surprised by how expressive it can make your code. Search your domain model for “State” or “Status” and see what Stateless can do!</p>  <p><em>This post also comes with a challenge: Stateless is fairly simple and very hackable - if you’re a fluent-interface aficionado and think you can improve the configuration API, join the project!</em></p>]]></content:encoded>
    </item>
  </channel>
</rss>