<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Leaning Into Windows : MEF</title><link>http://msmvps.com/blogs/kathleen/archive/tags/MEF/default.aspx</link><description>Tags: MEF</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>MEF and Cardinality Composition Failures</title><link>http://msmvps.com/blogs/kathleen/archive/2009/07/17/mef-and-cardinality-composition-failures.aspx</link><pubDate>Fri, 17 Jul 2009 13:44:24 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1702588</guid><dc:creator>Kathleen</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/kathleen/rsscomments.aspx?PostID=1702588</wfw:commentRss><comments>http://msmvps.com/blogs/kathleen/archive/2009/07/17/mef-and-cardinality-composition-failures.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;You can check &lt;a href="http://msmvps.com/blogs/kathleen/archive/2009/07/17/a-quick-description-of-mef.aspx"&gt;here&lt;/a&gt; for a quick description of MEF&lt;/em&gt;&lt;/p&gt; &lt;p&gt;I&amp;#39;m giving a half dozen MEF talks this summer and I&amp;#39;m frequently asked &amp;quot;what happens if a part isn&amp;#39;t available&amp;quot;. The old answer was &amp;quot;the system crashes, how could it do anything else?&amp;quot; This conversation definitely deflates the upbeat mood of a MEF talk. Recently, MEF has changed, making that answer obsolete.&lt;/p&gt; &lt;p&gt;MEF is a composition container which satisfies imports by tracking down associated exports. The correct number of exports to satisfy each import is called the cardinality and can be one, zero to one or zero to many. Thus an import can fail because there are too few or too many matching exports.&lt;/p&gt; &lt;p&gt;In the MEF previews 1-5 (inclusive) and in the Visual Studio CTPs and beta1, MEF throws an exception when a failure occurs.&lt;/p&gt; &lt;p&gt;MEF Preview 6, released last Monday, introduces &amp;quot;stable composition.&amp;quot; With stable composition, the container can know about, but not expose parts. If a part fails on a cardinality rule, the MEF container remembers the part, but keeps it hidden. If additional composition occurs (such as through the Refresh method) additional attempts to fully compose the part occur. If its cardinality is fulfilled, the part becomes available for additional composition. You can think of this as &amp;quot;if a missing sub part shows up later, the containing part will become available.&amp;quot;&lt;/p&gt; &lt;p&gt;There are both good and bad aspects of this, and it definitely affects how you think of and write your MEF systems. In general, it will make MEF apps more stable. If you design a plug-in model, and the creator of a plug-in fails to properly deploy (or a confused user deletes some but not all of a plug-in via File Explorer), your system will not crash. The containing part, which would probably fail if run, doesn&amp;#39;t appear in composition. This makes your system more robust against errors that are beyond your control. It also allows the late composition strategy, although I&amp;#39;m not yet clear on good scenarios for it.&lt;/p&gt; &lt;p&gt;The down side is that you may have more challenges finding certain types of composition errors because you will not receive an exception - you need to catch the current state of the composition container. And if you don&amp;#39;t consider this behavior when writing your app, you can get officially bad behavior. &lt;/p&gt; &lt;p&gt;In a plug-in design such as the directory composition model, any part in your system can fail on a cardinality (and could previously have crashed) because all parts can be made of other parts with dependencies you don&amp;#39;t know about. &lt;/p&gt; &lt;p&gt;For example, consider creating a main menu as a part and that menu is made up of menu items and sub menus and one of the menu items cannot be composed due to a deeply nested cardinality failure. If each main menu item is a part and you import the menu items as a collection using the ImportMany attribute, you&amp;#39;re fine. Your application will simply not display the failed menu item.As deep as the nesting goes, each layer that is a collection is naturally protected because cardinality failures just remove one part from the collection. &lt;/p&gt; &lt;p&gt;If instead you create your main menu to explicitly expect a particular menu item (such as a Tools sub menu) and that menu has a required Import for a part and so on down to a point of cardinality failure, then the failure cascades up the chain. This happens because the leaf cardinality failure means that part is not available, causing a cardinality failure at the next level. In this hypothetical case, the failure cascades all the way up to the main menu which does not now exist. The application either runs without a main menu, or the application fails because the main menu is missing.&lt;/p&gt; &lt;p&gt;You can avoid this by considering the intent of each import and providing appropriate protection. Some parts are optional and your application can run just fine without them. These should either be in a collection (ImportMany in recent previews) or not required. Other parts are important, but not important enough to cause their container to fail. These can be managed via asserts, and communication with support or the user. If parts are critical to the application running, then you need to check that they exist after composition and shut down the application as gracefully as possible. &lt;/p&gt; &lt;p&gt;I think this is a good change, but at least until more patterns emerge, you need to consider what would happen if any import is not successfully satisfied. Should the containing part also fail to be composed?&lt;/p&gt; &lt;p&gt;MEF is a very sharp knife. It cuts up the tomatoes and carrots really well and we can have a dandy stew. Or we can wind up in the emergency room. Understanding MEF is important to safe MEF use. &lt;/p&gt; &lt;p&gt;&lt;em&gt;You can find more on the Preview 6 changes in &lt;a href="http://blogs.msdn.com/nblumhardt/archive/2009/07/09/mef-preview-6-available.aspx"&gt;this&lt;/a&gt; post by &lt;a href="http://blogs.msdn.com/nblumhardt/default.aspx"&gt;Nicholas Blumhardt&lt;/a&gt; who is a member of the MEF team. I&amp;#39;d like to thank Glenn Block for his discussions with me on this change. &lt;/em&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1702588" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/kathleen/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/kathleen/archive/tags/MEF/default.aspx">MEF</category></item><item><title>MEF Assembly Granularity</title><link>http://msmvps.com/blogs/kathleen/archive/2009/03/15/mef-assembly-granularity.aspx</link><pubDate>Sun, 15 Mar 2009 15:25:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1678240</guid><dc:creator>Kathleen</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/kathleen/rsscomments.aspx?PostID=1678240</wfw:commentRss><comments>http://msmvps.com/blogs/kathleen/archive/2009/03/15/mef-assembly-granularity.aspx#comments</comments><description>&lt;p class="MsoNormal"&gt;I&amp;rsquo;ve been contemplating how to organize MEF assemblies. I think the processing I did establishing the first cut at organization, and the shake down of that strategy, may be interesting to other people designing MEF systems. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;As a quick review, MEF lets you throw parts into a MEF container and sort out how parts work together at runtime. Parts are recognized by a string identifier. I&amp;rsquo;m almost always using interfaces as the contract and the interface names as the identifiers. Parts reside within assemblies and in the common case assemblies are discovered because they are grouped into anticipated directories.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;With this approach, only the part implementing the interface and the part that is using the interface need to understand the interface or explicitly reference the interface&amp;rsquo;s assembly. And since parts are discovered and loaded at an assembly level, the granularity of implementing assemblies also controls the granularity of the load. I care about the assembly granularity of contract/interface assemblies so excess stuff can be avoided and naming conflicts (resolved via namespaces) are minimized. I care about the granularity of implementation assemblies because until I attain a priority system with additional granularity, prioritization/defaults are only as granular as their containing assemblies. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;At one extreme, all interfaces reside in one assembly and all implementations reside in another. It doesn&amp;rsquo;t make sense to put them into the same assembly as then hard coded references exist and ensuring isolation is difficult. At the other extreme, every interface and every implementation resides in its own assembly. I think both of these extremes are a terrible solution. That&amp;rsquo;s because this composable system (and I would think any composable system) have parts with very different roles and lineages/history. In the simplest sense for a generator - metadata providers and templates are fundamentally different and could easily be provided by different teams.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Initially I thought the primary consideration should be the implementation deployment, but&amp;nbsp;Phil Spidey pointed out in the MEF discussions that the interface organization is more important, because once released to the wild it might be hard to fix.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;I decided on six contract assemblies:&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" style="border-right:medium none;border-top:medium none;border-left:medium none;border-bottom:medium none;border-collapse:collapse;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-yfti-tbllook:1184;mso-padding-alt:0in 5.4pt 0in 5.4pt;" class="MsoTableGrid"&gt;

&lt;tr style="mso-yfti-irow:0;mso-yfti-firstrow:yes;"&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:black 1pt solid;padding-left:5.4pt;padding-bottom:0in;border-left:black 1pt solid;width:189.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;CommonContracts&lt;/p&gt;
&lt;/td&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:black 1pt solid;padding-left:5.4pt;padding-bottom:0in;border-left:medium none;width:288.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-left-alt:solid black .5pt;mso-border-left-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;Interfaces referenced by the template harness itself&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="mso-yfti-irow:1;"&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:black 1pt solid;width:189.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;CommonDatabaseMetadataContracts&lt;/p&gt;
&lt;/td&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:medium none;width:288.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-left-alt:solid black .5pt;mso-border-left-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;mso-border-bottom-themecolor:text1;mso-border-right-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;Interfaces sharing database structure&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="mso-yfti-irow:2;"&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:black 1pt solid;width:189.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;CommonDomainMetadataContracts&lt;/p&gt;
&lt;/td&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:medium none;width:288.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-left-alt:solid black .5pt;mso-border-left-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;mso-border-bottom-themecolor:text1;mso-border-right-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;Interfaces sharing business object structure&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="mso-yfti-irow:3;"&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:black 1pt solid;width:189.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;CommonNamingServiceContracts&lt;/p&gt;
&lt;/td&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:medium none;width:288.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-left-alt:solid black .5pt;mso-border-left-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;mso-border-bottom-themecolor:text1;mso-border-right-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;Interfaces for a naming service&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="mso-yfti-irow:4;"&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:black 1pt solid;width:189.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;CommonOutputServiceContracts&lt;/p&gt;
&lt;/td&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:medium none;width:288.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-left-alt:solid black .5pt;mso-border-left-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;mso-border-bottom-themecolor:text1;mso-border-right-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;Interfaces for outputting data, including hashing&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="mso-yfti-irow:5;mso-yfti-lastrow:yes;"&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:black 1pt solid;width:189.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;CommonServiceContracts&lt;/p&gt;
&lt;/td&gt;
&lt;td style="border-right:black 1pt solid;padding-right:5.4pt;border-top:medium none;padding-left:5.4pt;padding-bottom:0in;border-left:medium none;width:288.9pt;padding-top:0in;border-bottom:black 1pt solid;mso-border-alt:solid black .5pt;mso-border-themecolor:text1;mso-border-left-alt:solid black .5pt;mso-border-left-themecolor:text1;mso-border-top-alt:solid black .5pt;mso-border-top-themecolor:text1;mso-border-bottom-themecolor:text1;mso-border-right-themecolor:text1;"&gt;
&lt;p style="margin-bottom:0pt;line-height:normal;" class="MsoNormal"&gt;Miscellaneous interfaces that don&amp;rsquo;t fit elsewhere&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
&lt;p class="MsoNormal"&gt;&lt;br /&gt;I&amp;rsquo;ve used a few criteria for this design:&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Interfaces that are used by the system and therefore can&amp;rsquo;t easily be changed reside together in CommonContracts. The template harness also references CommonOutputServiceContracts but this is in a separate assembly because it has a distinct purpose, may evolve on a different time frame and you are far more likely to provide alternate implementations for output than for the core interfaces. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;The naming service is also a separate assembly because it is a distinct purpose and some people will certainly supply alternate implementations to manage human languages other than US English. Both the output service and naming service are a few distinct interfaces that work together. I also had a few odd ball interfaces and decided to go with a grab bag of miscellaneous interfaces rather than a separate assembly for each interface. Time will tell whether that is a good decision. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;I initially put the two metadata interfaces into a single assembly, but I think it&amp;rsquo;s quite likely that these interfaces will evolve separately and almost certain that they will be implemented independently. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;I&amp;rsquo;d like to note that the first version of the harness, which is almost, almost done (a separate blog post) will be a CTP /alpha level release. I will take feedback on the interfaces and I do expect them to change. A core part of the composable design is that you can spin off your interfaces/implementations so while these changes will be breaking, you can uptake them at your own pace. &lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1678240" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/kathleen/archive/tags/Code+Generation/default.aspx">Code Generation</category><category domain="http://msmvps.com/blogs/kathleen/archive/tags/MEF/default.aspx">MEF</category></item></channel></rss>