The blog of dlaa.me

Posts tagged "Technical"

TextAnalysisTool.NET to Windows 8: "Y U no run me under .NET 4?" [How to avoid the "please install .NET 3.5" dialog when running older .NET applications on the Windows 8 Developer Preview]

I wrote TextAnalysisTool.NET a number of years ago to streamline the task of analyzing large log files by creating an interactive experience that combines searching, filtering, and tagging and allow the user to quickly identify interesting portions of a large log file. Although .NET 2.0 was out at the time, I targeted .NET 1.1 because it was more widely available, coming pre-installed on Windows Server 2003 (the "latest and greatest" OS then). In the years since, I've heard from folks around the world running TextAnalysisTool.NET on subsequent Windows operating systems and .NET Framework versions. Because Windows and the .NET Framework do a great job maintaining backwards compatibility, the same TextAnalysisTool.NET binary has continued to work as-is for the near-decade since its initial release.

TextAnalysisTool.NET demonstration

 

But the story changes with Windows 8! Although Windows 8 has the new .NET 4.5 pre-installed (including .NET 4.0 upon which it's based), it does not include .NET 3.5 (and therefore .NET 2.0). While I can imagine some very sensible reasons for the Windows team to take this approach, it's inconvenient for existing applications because .NET 4 in this scenario does not automatically run applications targeting an earlier framework version. What is cool is that the public Windows 8 Developer Preview detects when an older .NET application is run and automatically prompts the user to install .NET 3.5:

Windows 8 .NET 3.5 install prompt

That's pretty slick and is a really nice way to bridge the gap. However, it's still kind of annoying for users as it may not always be practical for them to perform a multi-megabyte download the first time they try to run an older .NET program. So it would be nice if there were an easy way for older .NET applications to opt into running under the .NET 4 framework that's already present on Windows 8...

And there is! :) One aspect of .NET's "side-by-side" support involves using .config files to specify which .NET versions an application is known to work with. (For more information, please refer to the MSDN article How to: Use an Application Configuration File to Target a .NET Framework Version.) Consequently, improving the Windows 8 experience for TextAnalisisTool.NET should be as easy as creating a suitable TextAnalysisTool.NET.exe.config file in the same folder as TextAnalysisTool.NET.exe.

 

Specifically, the following should do the trick:

<?xml version="1.0"?>
<configuration>
  <startup>
    <supportedRuntime version="v1.1.4322"/>
    <supportedRuntime version="v2.0.50727"/>
    <supportedRuntime version="v4.0"/>
  </startup>
</configuration>

And it does! :) With that TextAnalysisTool.NET.exe.config file in place, TextAnalysisTool.NET runs on a clean install of the Windows 8 Developer Preview as-is and without prompting the user to install .NET 3.5. I've updated the download ZIP to include this file so new users will automatically benefit; existing users should drop TextAnalysisTool.NET.exe.config in the right place, and they'll be set as well!

Aside: Although this trick will work in many cases, it isn't guaranteed to work. In particular, if there has been a breaking change in .NET 4, then attempting to run a pre-.NET 4 application in this manner might fail. Therefore, it's prudent to do some verification when trying a change like this!

 

[Click here to download a ZIP file containing TextAnalysisTool.NET, the relevant .config file, its documentation, and a ReadMe.]

 

TextAnalysisTool.NET has proven to be extremely popular with support engineers and it's always nice to hear from new users. I hope today's post extends the usefulness of TextAnalysisTool.NET by making the Windows 8 experience as seamless as people have come to expect!

Preprocessor? .NET don't need no stinkin' preprocessor! [DebugEx.Assert provides meaningful assertion failure messages automagically!]

If you use .NET's Debug.Assert method, you probably write code to validate assumptions like so:

Debug.Assert(args == null);

If the expression above evaluates to false at run-time, .NET immediately halts the program and informs you of the problem:

Typical Debug.Assert

The stack trace can be really helpful (and it's cool you can attach a debugger right then!), but it would be even more helpful if the message told you something about the faulty assumption... Fortunately, there's an overload of Debug.Assert that lets you provide a message:

Debug.Assert(args == null, "args should be null.");

The failure dialog now looks like this:

Debug.Assert with message

That's a much nicer experience - especially when there are lots of calls to Assert and you're comfortable ignoring some of them from time to time (for example, if a network request failed and you know there's no connection). Some code analysis tools (notably StyleCop) go as far as to flag a warning for any call to Assert that doesn't provide a custom message.

At first, adding a message to every Assert seems like it ought to be pure goodness, but there turn out to be some drawbacks in practice:

  • The comment is often a direct restatement of the code - especially for very simple conditions. Redundant redundancy is redundant, and when I see messages like that, I'm reminded of code comments like this:

    i++; // Increment i
  • It takes time and energy to type out all those custom messages, and the irony is that most of them will never be seen at all!

 

Because the code for the condition is often expressive enough as-is, it would be nice if Assert automatically used the code as the message!

Aside: This is hardly a new idea; C developers have been doing this for years by leveraging macro magic in the preprocessor to create a string from the text of the condition.
Further aside: This isn't even a new idea for .NET; I found a couple places on the web where people ask how to do this. And though nobody I saw seemed to have done quite what I show here, I'm sure there are other examples of this technique "in the wild".

As it happens, displaying the code for a condition can be accomplished fairly easily in .NET without introducing a preprocessor! However, it requires that calls to Assert be made slightly differently so as to defer execution of the condition. In a normal call to Assert, the expression passed to the condition parameter is completely evaluated before being checked. But by changing the type of the condition parameter from bool to Func<bool> and then wrapping it in the magic Expression<Func<bool>>, we're able to pass nearly complete information about the expression into the Assert method where it can be used to recreate the original source code at run-time!

 

To make this a little more concrete, the original "message-less" call I showed at the beginning of the post can be trivially changed to:

DebugEx.Assert(() => args == null);

And the DebugEx.Assert method I've written will automatically provide a meaningful message (by calling the real Debug.Assert and passing the condition and a message):

DebugEx.Assert with automatic message

 

The message above is identical to the original code - but maybe that's because it's so simple... Let's try something more complex:

DebugEx.Assert(() => args.Select(a => a.Length).Sum() == 10);

Becomes:

Assertion Failed: (args.Select(a => a.Length).Sum() == 10)

Wow, amazing! So is it always perfect? Unfortunately, no:

DebugEx.Assert(() => args.Length == 5);

Becomes:

Assertion Failed: (ArrayLength(args) == 5)

The translation of the code to an expression tree and back seems to have lost a little fidelity along the way; the compiler translated the Length access into an expression tree that doesn't map back to code exactly the same. Similarly:

DebugEx.Assert(() => 5 + 3 + 2 >= 100);

Becomes:

Assertion Failed: False

In this case, the compiler evaluated the constant expression at compile time (it's constant, after all!), and the information about which numbers were used in the computation was lost.

Yep, the loss of fidelity in some cases is a bit of a shame, but I'll assert (ha ha!) that nearly all the original intent is preserved and that it's still quite easy to determine the nature of the failing code without having to provide a message. And of course, you can always switch an ambiguous DebugEx.Assert back to a normal Assert and provide a message parameter whenever you want. :)

 

[Click here to download the source code for DebugEx.Assert and the sample application used for the examples above.]

 

DebugEx.Assert was a fun experiment and a great introduction to .NET's powerful expression infrastructure. DebugEx.Assert is a nearly-direct replacement for Debug.Assert and (similarly) applies only when DEBUG is defined, so it costs nothing in release builds. It's worth noting there will be a bit of extra overhead due to the lambda, but it should be negligible - especially when compared to the time you'll save by not having to type out a bunch of unnecessary messages!

If you're getting tired of typing the same code twice, maybe DebugEx.Assert can help! :)

 

Notes:

  • The code for DebugEx.Assert turned out to be simple because nearly all the work is done by the Expression(T) class. The one bit of trickiness stems from the fact that in order to create a lambda to pass as the Func(T), the compiler creates a closure which introduces an additional class (though they're never exposed to the developer). Therefore, even simple statements like the original example become kind of hard to read: Assertion Failed: (value(Program+<>c__DisplayClass0).args == null).

    To avoid that problem, I created an ExpressionVisitor subclass to rewrite the expression tree on the fly, getting rid of the references to such extra classes along the way. What I've done with SimplifyingExpressionVisitor is simple, but seems to work nicely for the things I've tried. However, if you find scenarios where it doesn't work as well, I'd love to know so I can handle them too!

Tags: Technical

Use it or lose it, part deux [New Delay.FxCop code analysis rule helps identify uncalled public or private methods and properties in a .NET assembly]

Previous posts introduced the Delay.FxCop custom code analysis assembly and demonstrated the benefits of automated code analysis for easily identifying problem areas in an assembly. The Delay.FxCop project included two rules, DF1000: Check spelling of all string literals and DF1001: Resources should be referenced - today I'm introducing another! The new rule follows in the footsteps of DF1001 by identifying unused parts of an assembly that can be removed to save space and reduce complexity. But while DF1001 operated on resources, today's DF1002: Uncalled methods should be removed analyzes the methods and properties of an assembly to help find those stale bits of code that aren't being used any more.

Note: If this functionality seems familiar, it's because CA1811: Avoid uncalled private code is one of the standard FxCop rules. I've always been a big fan of CA1811, but frequently wished it could look beyond just private code to consider all code. Of course, limiting the scope of the "in-box" rule makes perfect sense from an FxCop point of view: you don't want the default rules to be noisy or else they'll get turned off and ignored. But the Delay.FxCop assembly isn't subject to the same restrictions, so I thought it would be neat to experiment with an implementation that analyzed all of an assembly's code.
Further note: One of the downsides of this increased scope is that DF1002 can't distinguish between methods that are part of a library's public API and those that are accidentally unused. As far as DF1002 is concerned, they're both examples of code that's not called from within the assembly. Therefore, running this rule on a library involves some extra overhead to suppress the warnings for public APIs. If it's just a little extra work, maybe it's still worthwhile - but if it's overwhelming, you can always disable DF1002 for library assemblies and restrict it to applications where it's more relevant.

 

Implementation-wise, DF1002: Uncalled methods should be removed isn't all that different from its predecessors - in fact, it extends and reuses the same assembly node enumeration helper introduced with DF1001. During analysis, every method of the assembly is visited and if it isn't "used" (more on this in a moment), a code analysis warning is output:

DF1002 : Performance : The method 'SilverlightApplication.MainPage.UnusedPublicMethod' does not appear to be used in code.

Of course, these warnings can be suppressed in the usual manner:

[assembly: SuppressMessage("Usage", "DF1001:ResourcesShouldBeReferenced",
           MessageId = "app.xaml", Scope = "resource", Target = "SilverlightApplication.g.resources",
           Justification = "Loaded by Silverlight for App.xaml.")]

 

It's interesting to consider what it means for a method or a property to be "used"... (Internally, properties are implemented as a pair of get/set methods.) Clearly, a direct call to a method means it's used - but that logic alone results in a lot of false positives! For example, a class implementing an interface must define all the relevant interface methods in order to compile successfully. Therefore, explicit and implicit interface method implementations (even if uncalled) do not result in a DF1002 warning. Similarly, a method override may not be directly called within an assembly, but can still be executed and should not trigger a warning. Other kinds of "unused" methods that do not result in a warning include: static constructors, assembly entry-points, and methods passed as parameters (ex: to a delegate for use by an event).

With all those special cases, you might think nothing would ever be misdiagnosed. :) But there's a particular scenario that leads to many DF1002 warnings in a perfectly correct application: reflection-based access to properties and methods. Granted, reflection is rare at the application level - but at the framework level, it forms the very foundation of data binding as implemented by WPF and Silverlight! Therefore, running DF1002 against a XAML application with data binding can result in warnings for the property getters on all model classes...

To avoid that problem, I've considered whether it would make sense to suppress DF1002 for classes that implement INotifyPropertyChanged (which most model classes do), but it seems like that would also mask a bunch of legitimate errors. The same reasoning applies to subclasses of DependencyObject or implementations of DependencyProperty (though the latter might turn out to be a decent heuristic with a bit more work). Another approach might be for the rule to also parse the XAML in an assembly and identify the various forms of data binding within. That seems promising, but goes way beyond the initial scope of DF1002! :)

Of course, there may be other common patterns which generate false positives - please let me know if you find one and I'll look at whether I can improve things for the next release.

 

[Click here to download the Delay.FxCop rule assembly, associated .ruleset files, samples, and the complete source code.]

For directions about running Delay.FxCop on a standalone assembly or integrating it into a project, please refer to the steps in my original post.

 

Unused code is an unnecessary tax on the development process. It's a distraction when reading, incurs additional costs during coding (ex: when refactoring), and it can mislead others about how an application really works. That's why there's DF1002: Uncalled methods should be removed - to help you easily identify unused methods. Try running it on your favorite .NET application; you might be surprised by what you find! :)

Tags: Technical

Use it or lose it! [New Delay.FxCop code analysis rule helps identify unused resources in a .NET assembly]

My previous post outlined the benefits of automated code analysis and introduced the Delay.FxCop custom code analysis assembly. The initial release of Delay.FxCop included only one rule, DF1000: Check spelling of all string literals, which didn't seem like enough to me, so today's update doubles the number of rules! :) The new rule is DF1001: Resources should be referenced - but before getting into that I'm going to spend a moment more on spell-checking...

 

What I planned to write for the second code analysis rule was something to check the spelling of .NET string resources (i.e., strings from a RESX file). This seemed like another place misspellings might occur and I'd heard of other custom rules that performed this same task (for example, here's a sample by Jason Kresowaty). However, in the process of doing research, I discovered rule CA1703: Resource strings should be spelled correctly which is part of the default set of rules!

To make sure it did what I expected, I started a new application, added a misspelled string resource, and ran code analysis. To my surprise, the misspelling was not detected... However, I noticed a different warning that seemed related: CA1824: Mark assemblies with NeutralResourcesLanguageAttribute "Because assembly 'Application.exe' contains a ResX-based resource file, mark it with the NeutralResourcesLanguage attribute, specifying the language of the resources within the assembly." Sure enough, when I un-commented the (project template-provided) NeutralResourcesLanguage line in AssemblyInfo.cs, the desired warning showed up:

CA1703 : Microsoft.Naming : In resource 'WpfApplication.Properties.Resources.resx', referenced by name
'SampleResource', correct the spelling of 'mispelling' in string value 'This string has a mispelling.'.

In my experience, a some people suppress CA1824 instead of addressing it. But as we've just discovered, they're also giving up on free spell checking for their assembly's string resources. That seems silly, so I recommend setting NeutralResourcesLanguageAttribute for its helpful side-effects!

Note: For expository purposes, I've included an example in the download: CA1703 : Microsoft.Naming : In resource 'WpfApplication.Properties.Resources.resx', referenced by name 'IncorrectSpelling', correct the spelling of 'mispelling' in string value 'This string has a single mispelling.'.

 

Once I realized resource spell checking was unnecessary, I decided to focus on a different pet peeve of mine: unused resources in an assembly. In much the same way stale chunks of unused code can be found in most applications, it's pretty common to find resources that aren't referenced and are just taking up valuable space. But while there's a built-in rule to detect certain kinds of uncalled code (CA1811: Avoid uncalled private code), I'm not aware of anything similar for resources... And though it's possible to perform this check manually (by searching for the use of each individual resource), this is the kind of boring, monotonous task that computers are made for! :)

Therefore, I've created the second Delay.FxCop rule, DF1001: Resources should be referenced, which compares the set of resource references in an assembly with the set of resources that are actually present. Any cases where a resource exists (whether it's a string, stream, or object), but is not referenced in code will result in an instance of the DF1001 warning during code analysis.

Aside: For directions about how to run the Delay.FxCop rules on a standalone assembly or integrate them into a project, please refer to the steps in my original post.

As a word of caution, there can be cases where DF1001 reports that a resource isn't referenced from code, but that resource is actually used by an assembly. While I don't think it will miss typical uses from code (either via the automatically-generated Resources class or one of the lower-level ResourceManager methods), the catch is that not all resource references show up in code! For example, the markup for a Silverlight or WPF application is included as a XAML/BAML resource which is loaded at run-time without an explicit reference from the assembly itself. DF1001 will (correctly; sort of) report this resource as unused, so please remember that global code analysis suppressions can be used to squelch false-positives:

[assembly: SuppressMessage("Usage", "DF1001:ResourcesShouldBeReferenced", MessageId = "mainwindow.baml",
    Scope = "resource", Target = "WpfApplication.g.resources", Justification = "Loaded by WPF for MainWindow.xaml.")]
Aside: There are other ways to "fool" DF1001, such as by loading a resource from a different assembly or passing a variable to ResourceManager.GetString. But in terms of how things are done 95% of the time, the rule's current implementation should be accurate. Of course, if you find cases where it misreports unused resources, please let me know and I'll look into whether it's possible to improve things in a future release!

 

[Click here to download the Delay.FxCop rule assembly, associated .ruleset files, samples, and the complete source code.]

 

Stale references are an unnecessary annoyance: they bloat an assembly, waste time and money (for example, when localized unnecessarily), confuse new developers, and generally just get in the way. Fortunately, detecting them in an automated fashion is easy with DF1001: Resources should be referenced! After making sure unused resources really are unused, remove them from your project - and enjoy the benefits of a smaller, leaner application!

Tags: Technical

Speling misteaks make an aplikation look sily [New Delay.FxCop code analysis rule finds spelling errors in a .NET assembly's string literals]

No matter how polished the appearance of an application, web site, or advertisement is, the presence of even a single spelling error can make it look sloppy and unprofessional. The bad news is that spelling errors are incredibly easy to make - either due to mistyping or because one forgot which of the many, conflicting special cases applies in a particular circumstance. The good news is that technology to detect and correct spelling errors exists and is readily available. By making regular use of a spell-checker, you don't have to be a good speller to look like one. Trust me! ;)

Spell-checking of documents is pretty well covered these days, with all the popular word processors offering automated, interactive assistance. However, spell-checking of code is not quite so far along - even high-end editors like Visual Studio don't tend to offer interactive spell-checking support. Fortunately, it's possible - even easy! - to augment the capabilities of many development tools to integrate spell-checking into the development workflow. There are a few different ways of doing this: one is to incorporate the checking into the editing experience (like this plugin by coworker Mikhail Arkhipov) and another is to do the checking as part of the code analysis workflow (like code analysis rule CA1703: ResourceStringsShouldBeSpelledCorrectly). I'd already been toying with the idea of implementing my own code analysis rules, so I decided to experiment with the latter approach...

Aside: If you're not familiar with Visual Studio's code analysis feature, I highly recommend the MSDN article Analyzing Managed Code Quality by Using Code Analysis. Although the fully integrated experience is only available on higher-end Visual Studio products, the same exact code analysis functionality is available to everyone with the standalone FxCop tool which is free as part of the Microsoft Windows SDK for Windows 7 and .NET Framework 4. (FxCop has a dedicated download page with handy links, but it directs you to the SDK to do the actual install.)
Unrelated aside: In the ideal world, all of an application's strings would probably come from a resource file where they can be easily translated to other languages - and therefore string literals wouldn't need spell-checking. However, in the real world, there are often cases where user-visible text ends up in string literals (ex: exception messages) and therefore a rule like this seems to have practical value. If the string resources of your application are already perfectly separated, congratulations! However, if your application doesn't use resources (or uses them incompletely!), please continue reading... :)

 

As you might expect, it's possible to create custom code analysis rules and easily integrate them into your build environment; a great walk-through can be found on the Code Analysis Team Blog. If you still have questions after reading that, this post by Tatham Oddie is also quite good. And once you have an idea what you're doing, this documentation by Jason Kresowaty is a great resource for technical information.

Code analysis is a powerful tool and has a lot of potential for improving the development process. But for now, I'm just going to discuss a single rule I created: DF1000: CheckSpellingOfAllStringLiterals. As its name suggests, this rule checks the spelling of all string literals in an assembly. To be clear, there are other rules that check spelling (including some of the default FxCop/Visual Studio ones), but I didn't see any that checked all the literals, so this seemed like an interesting place to start.

Aside: Programs tend to have a lot of strings and those strings aren't always words (ex: namespace prefixes, regular expressions, etc.). Therefore, this rule will almost certainly report a lot of warnings run for the first time! Be prepared for that - and be ready to spend some time suppressing warnings that don't matter to you. :)

 

As I typically do, I've published a pre-compiled binary and complete source code, so you can see exactly how CheckSpellingOfAllStringLiterals works (it's quite simple, really, as it uses the existing introspection and spell-checking APIs). I'm not going to spend a lot of time talking about how this rule is implemented, but I did want to show how to use it so others can experiment with their own projects.

Important: Everything I show here was done with the Visual Studio 2010/.NET 4 toolset. Past updates to the code analysis infrastructure are such that things may not work with older (or newer) releases.

To add the Delay.FxCop rules to a project, you'll want to know a little about rule sets - the MSDN article Using Rule Sets to Group Managed Code Analysis Rules is a good place to start. I've provided two .ruleset files in the download: Delay.FxCop.ruleset which contains just the custom rule I've written and AllRules_Delay.FxCop.ruleset which contains my custom rule and everything in the shipping "Microsoft All Rules" ruleset. (Of course, creating and using your own .ruleset is another option!) Incorporating a custom rule set into a Visual Studio project is as easy as: Project menu, ProjectName Properties..., Code Analysis tab, Run this rule set:, Browse..., specify the path to the custom rule set, Build menu, Run Code Analysis on ProjectName.

Note: For WPF projects, you may also want to uncheck Suppress results from generated code in the "Code Analysis" tab above because the XAML compiler adds GeneratedCodeAttribute to all classes with an associated .xaml file and that automatically suppresses code analysis warnings for those classes. (Silverlight and Windows Phone projects don't set this attribute, so the default "ignore" behavior is fine.)

Assuming your project contains a string literal that's not in the dictionary, the Error List window should show one or more warnings like this:

DF1000 : Spelling : The word 'recieve' is not in the dictionary.

At this point, you have a few options (examples of which can be found in the TestProjects\ConsoleApplication directory of the sample):

  • Fix the misspelling.

    Duh. :)

  • Suppress the instance.

    If it's an isolated use of the word and is correct, then simply right-clicking the warning and choosing Suppress Message(s), In Source will add something like the following attribute to the code which will silence the warning:

    [SuppressMessage("Spelling", "DF1000:CheckSpellingOfAllStringLiterals", MessageId = "leet")]

    While you're at it, feel free to add a Justification message if the reason might not be obvious to someone else.

  • Suppress the entire method.

    If a method contains no user-visible text, but has lots of strings that cause warnings, you can suppress the entire method by omitting the MessageId parameter like so:

    [SuppressMessage("Spelling", "DF1000:CheckSpellingOfAllStringLiterals")]
  • Add the word to the custom dictionary.

    If the "misspelled" word is correct and appears throughout the application, you'll probably want to add it to the project's custom dictionary which will silence all relevant warnings at once. MSDN has a great overview of the custom dictionary format as well as the exact steps to take to add a custom dictionary to a project in the article How to: Customize the Code Analysis Dictionary.

 

Alternatively, if you're a command-line junkie or don't want to modify your Visual Studio project, you can use FxCopCmd directly by running it from a Visual Studio Command Prompt like so:

C:\T>"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\FxCopCmd.exe"
  /file:C:\T\ConsoleApplication\bin\Debug\ConsoleApplication.exe
  /ruleset:=C:\T\Delay.FxCop\Delay.FxCop.ruleset /console
Microsoft (R) FxCop Command-Line Tool, Version 10.0 (10.0.30319.1) X86
Copyright (C) Microsoft Corporation, All Rights Reserved.

[...]
Loaded delay.fxcop.dll...
Loaded ConsoleApplication.exe...
Initializing Introspection engine...
Analyzing...
Analysis Complete.
Writing 1 messages...

C:\T\ConsoleApplication\Program.cs(12,1) : warning  : DF1000 : Spelling : The word 'recieve' is not in the dictionary.
Done:00:00:01.4352025

Or else you can install the standalone FxCop tool to get the benefits of a graphical user interface without changing anything about your existing workflow!

 

[Click here to download the Delay.FxCop rule assembly, associated .ruleset files, samples, and the complete source code.]

 

Spelling is one of those things that's easy to get wrong - and also easy to get right if you apply the proper technology and discipline. I can't hope to make anyone a better speller ('i' before 'e', except after 'c'!), but I can help out a little on the technology front. I plan to add new code analysis rules to Delay.FxCop over time - but for now I hope people put DF1000: CheckSpellingOfAllStringLiterals to good use finding spelling mistakes in their applications!

Tags: Technical

Safe X (ml parsing with XLINQ) [XLinqExtensions helps make XML parsing with .NET's XLINQ a bit safer and easier]

XLINQ (aka LINQ-to-XML) is a set of classes that make it simple to work with XML by exposing the element tree in a way that's easy to manipulate using standard LINQ queries. So, for example, it's trivial to write code to select specific nodes for reading, create well-formed XML fragments, or transform an entire document. Because of its query-oriented nature, XLINQ makes it easy to ignore parts of a document that aren't relevant: if you don't query for them, they don't show up! Because it's so handy and powerful, I encourage folks who aren't already familiar to find out more.

Aside: As usual, flexibility comes with a cost and it is often more efficient to read and write XML with the underlying XmlReader and XmlWriter classes because they don't expose the same high-level abstractions. However, I'll suggest that the extra productivity of developing with XLINQ will often outweigh the minor computational cost it incurs.

 

When I wrote the world's simplest RSS reader as a sample for my post on WebBrowserExtensions, I needed some code to parse the RSS feed for my blog and dashed off the simplest thing possible using XLINQ. Here's a simplified version of that RSS feed for reference:

<rss version="2.0">
  <channel>
    <title>Delay's Blog</title>
    <item>
      <title>First Post</title>
      <pubDate>Sat, 21 May 2011 13:00:00 GMT</pubDate>
      <description>Post description.</description>
    </item>
    <item>
      <title>Another Post</title>
      <pubDate>Sun, 22 May 2011 14:00:00 GMT</pubDate>
      <description>Another post description.</description>
    </item>
  </channel>
</rss>

The code I wrote at the time looked a lot like the following:

private static void NoChecking(XElement feedRoot)
{
    var version = feedRoot.Attribute("version").Value;
    var title = feedRoot.Element("channel").Element("title").Value;
    ShowFeed(version, title);
    foreach (var item in feedRoot.Element("channel").Elements("item"))
    {
        title = item.Element("title").Value;
        var publishDate = DateTime.Parse(item.Element("pubDate").Value);
        var description = item.Element("description").Value;
        ShowItem(title, publishDate, description);
    }
}

Not surprisingly, running it on the XML above leads to the following output:

Delay's Blog (RSS 2.0)
  First Post
    Date: 5/21/2011
    Characters: 17
  Another Post
    Date: 5/22/2011
    Characters: 25

 

That code is simple, easy to read, and obvious in its intent. However (as is typical for sample code tangential to the topic of interest), there's no error checking or handling of malformed data. If anything within the feed changes, it's quite likely the code I show above will throw an exception (for example: because the result of the Element method is null when the named element can't be found). And although I don't expect changes to the format of this RSS feed, I'd be wary of shipping code like that because it's so fragile.

Aside: Safely parsing external data is a challenging task; many exploits take advantage of parsing errors to corrupt a process's state. In the discussion here, I'm focusing mainly on "safety" in the sense of "resiliency": the ability of code to continue to work (or at least not throw an exception) despite changes to the format of the data it's dealing with. Naturally, more resilient parsing code is likely to be less vulnerable to hacking, too - but I'm not specifically concerned with making code hack-proof here.

 

Adding the necessary error-checking to get the above snippet into shape for real-world use isn't particularly hard - but it does add a lot more code. Consequently, readability suffers; although the following method performs exactly the same task, its implementation is decidedly harder to follow than the original:

private static void Checking(XElement feedRoot)
{
    var version = "";
    var versionAttribute = feedRoot.Attribute("version");
    if (null != versionAttribute)
    {
        version = versionAttribute.Value;
    }
    var channelElement = feedRoot.Element("channel");
    if (null != channelElement)
    {
        var title = "";
        var titleElement = channelElement.Element("title");
        if (null != titleElement)
        {
            title = titleElement.Value;
        }
        ShowFeed(version, title);
        foreach (var item in channelElement.Elements("item"))
        {
            title = "";
            titleElement = item.Element("title");
            if (null != titleElement)
            {
                title = titleElement.Value;
            }
            var publishDate = DateTime.MinValue;
            var pubDateElement = item.Element("pubDate");
            if (null != pubDateElement)
            {
                if (!DateTime.TryParse(pubDateElement.Value, out publishDate))
                {
                    publishDate = DateTime.MinValue;
                }
            }
            var description = "";
            var descriptionElement = item.Element("description");
            if (null != descriptionElement)
            {
                description = descriptionElement.Value;
            }
            ShowItem(title, publishDate, description);
        }
    }
}

 

It would be nice if we could somehow combine the two approaches to arrive at something that reads easily while also handling malformed content gracefully... And that's what the XLinqExtensions extension methods are all about!

Using the naming convention SafeGet* where "*" can be Element, Attribute, StringValue, or DateTimeValue, these methods are simple wrappers that avoid problems by always returning a valid object - even if they have to create an empty one themselves. In this manner, calls that are expected to return an XElement always do; calls that are expected to return a DateTime always do (with a user-provided fallback value for scenarios where the underlying string doesn't parse successfully). To be clear, there's no magic here - all the code is very simple - but by pushing error handling into the accessor methods, the overall experience feels much nicer.

To see what I mean, here's what the same code looks like after it has been changed to use XLinqExtensions - note how similar it looks to the original implementation that used the simple "write it the obvious way" approach:

private static void Safe(XElement feedRoot)
{
    var version = feedRoot.SafeGetAttribute("version").SafeGetStringValue();
    var title = feedRoot.SafeGetElement("channel").SafeGetElement("title").SafeGetStringValue();
    ShowFeed(version, title);
    foreach (var item in feedRoot.SafeGetElement("channel").Elements("item"))
    {
        title = item.SafeGetElement("title").SafeGetStringValue();
        var publishDate = item.SafeGetElement("pubDate").SafeGetDateTimeValue(DateTime.MinValue);
        var description = item.SafeGetElement("description").SafeGetStringValue();
        ShowItem(title, publishDate, description);
    }
}

Not only is the XLinqExtensions version almost as easy to read as the simple approach, it has all the resiliancy benefits of the complex one! What's not to like?? :)

 

[Click here to download the XLinqExtensions sample application containing everything shown here.]

 

I've found the XLinqExtensions approach helpful in my own projects because it enables me to parse XML with ease and peace of mind. The example I've provided here only scratches the surface of what's possible (ex: SafeGetIntegerValue, SafeGetUriValue, etc.), and is intended to set the stage for others to adopt a more robust approach to XML parsing. So if you find yourself parsing XML, please consider something similar!

 

PS - The complete set of XLinqExtensions methods I use in the sample is provided below. Implementation of additional methods to suit custom scenarios is left as an exercise to the reader. :)

/// <summary>
/// Class that exposes a variety of extension methods to make parsing XML with XLINQ easier and safer.
/// </summary>
static class XLinqExtensions
{
    /// <summary>
    /// Gets the named XElement child of the specified XElement.
    /// </summary>
    /// <param name="element">Specified element.</param>
    /// <param name="name">Name of the child.</param>
    /// <returns>XElement instance.</returns>
    public static XElement SafeGetElement(this XElement element, XName name)
    {
        Debug.Assert(null != element);
        Debug.Assert(null != name);
        return element.Element(name) ?? new XElement(name, "");
    }

    /// <summary>
    /// Gets the named XAttribute of the specified XElement.
    /// </summary>
    /// <param name="element">Specified element.</param>
    /// <param name="name">Name of the attribute.</param>
    /// <returns>XAttribute instance.</returns>
    public static XAttribute SafeGetAttribute(this XElement element, XName name)
    {
        Debug.Assert(null != element);
        Debug.Assert(null != name);
        return element.Attribute(name) ?? new XAttribute(name, "");
    }

    /// <summary>
    /// Gets the string value of the specified XElement.
    /// </summary>
    /// <param name="element">Specified element.</param>
    /// <returns>String value.</returns>
    public static string SafeGetStringValue(this XElement element)
    {
        Debug.Assert(null != element);
        return element.Value;
    }

    /// <summary>
    /// Gets the string value of the specified XAttribute.
    /// </summary>
    /// <param name="attribute">Specified attribute.</param>
    /// <returns>String value.</returns>
    public static string SafeGetStringValue(this XAttribute attribute)
    {
        Debug.Assert(null != attribute);
        return attribute.Value;
    }

    /// <summary>
    /// Gets the DateTime value of the specified XElement, falling back to a provided value in case of failure.
    /// </summary>
    /// <param name="element">Specified element.</param>
    /// <param name="fallback">Fallback value.</param>
    /// <returns>DateTime value.</returns>
    public static DateTime SafeGetDateTimeValue(this XElement element, DateTime fallback)
    {
        Debug.Assert(null != element);
        DateTime value;
        if (!DateTime.TryParse(element.Value, out value))
        {
            value = fallback;
        }
        return value;
    }
}
Tags: Technical

Images in a web page: meh... Images *in* a web page: cool! [Delay.Web.Helpers assembly now includes an ASP.NET web helper for data URIs (in addition to Amazon S3 blob/bucket support)]

Delay.Web.Helpers DataUri sample page

The topic of "data URIs" came up on a discussion list I follow last week in the context of "I'm in the process of creating a page and have the bytes of an image from my database. Can I deliver them directly or must I go through a separate URL with WebImage?" And the response was that using a data URI would allow that page to deliver the image content inline. But while data URIs are fairly simple, there didn't seem to be a convenient way to use them from an ASP.NET MVC/Razor web page.

Which was kind of fortuitous for me because I've been interested in learning more about data URIs for a while and it seemed that creating a web helper for this purpose would be fun. Better yet, I'd already released the Delay.Web.Helpers assembly (with support for Amazon S3 blob/bucket access), so I had the perfect place to put the new DataUri class once I wrote it! :)

Aside: For those who aren't familiar, the WebImage class provides a variety of handy methods for dealing with images on the server - including a Write method for sending them to the user's browser. However, the Write method needs to be called from a dedicated page that serves up just the relevant image, so it isn't a solution for the original scenario.

 

In case you've not heard of them before, data URIs are a kind of URL scheme documented by RFC 2397. They're quite simple, really - here's the relevant part of the specification:

data:[<mediatype>][;base64],<data>

dataurl    := "data:" [ mediatype ] [ ";base64" ] "," data
mediatype  := [ type "/" subtype ] *( ";" parameter )
data       := *urlchar
parameter  := attribute "=" value

It takes two pieces of information to create a data URI: the data and its media type (ex: "image/png"). (Although the media type appears optional above, it defaults to "text/plain" when absent - which is unsuitable for most common data URI scenarios.) Pretty much the only interesting thing you can do with data URIs on the server is write them, so the DataUri web helper exposes a single Write method with five flavors. The media type is always passed as a string (feel free to use the MediaTypeNames class to help here), but the data can be provided as a file name string, byte[], IEnumerable<byte>, or Stream. That's four methods; the fifth one takes just the file name string and infers the media type from the file's extension (ex: ".png" -> "image/png").

Aside: Technically, it would be possible for the other methods to infer media type as well by examining the bytes of data. However, doing so would require quite a bit more work and would always be subject to error. On the other hand, inferring media type from the file's extension is computationally trivial and much more likely to be correct in practice.

 

For an example of the DataUri helper in action, here's the Razor code to implement the "image from the database" scenario that started it all:

@{
    IEnumerable<dynamic> databaseImages;
    using (var database = Database.Open("Delay.Web.Helpers.Sample.Database"))
    {
        databaseImages = database.Query("SELECT * FROM Images");
    }

    // ...

    foreach(var image in databaseImages)
    {
        <p>
            <img src="@DataUri.Write(image.Content, image.MediaType)" alt="@image.Name"
                 width="@image.Width" height="@image.Height" style="vertical-align:middle"/>
            @image.Name
        </p>
    }
}

Easy-peasy lemon-squeezy!

 

And here's an example of using the file name-only override for media type inference:

<script src="@DataUri.Write(Server.MapPath("Sample-Script.js"))" type="text/javascript"></script>

Which comes out like this in the HTML that's sent to the browser:

<script src="data:text/javascript;base64,77u/ZG9j...PicpOw==" type="text/javascript"></script>
Aside: This particular example (using a data URI for a script file) doesn't render in all browsers. Specifically, Internet Explorer 8 (and earlier) blocks script delivered like this because of security concerns. Fortunately, Internet Explorer 9 has addressed those concerns and renders as expected. :)

 

[Click here to download the Delay.Web.Helpers assembly, complete source code, automated tests, and the sample web site.]

[Click here to go to the NuGet page for Delay.Web.Helpers which includes the DLL and its associated documentation/IntelliSense XML file.]

[Click here to go to the NuGet page for the Delay.Web.Helpers.SampleWebSite which includes the sample site that demonstrates everything.]

 

Data URIs are pretty neat things - though it's important to be aware they have their drawbacks as well. Fortunately, the Wikipedia article does a good job discussing the pros and cons, so I highly recommend looking it over before converting all your content. :) Creating a data URI manually isn't rocket science, but it is the kind of thing ASP.NET web helpers are perfectly suited for. If you're a base-64 nut, maybe you'll continue doing this by hand - but for everyone else, I hope the new DataUri class in the Delay.Web.Helpers assembly proves useful!

What next, a DOS version?? [Free tool and source code to temporarily prevent a computer from entering sleep mode - 32-bit and 64-bit versions now support Windows XP!]

I used .NET 3.5 to write the first version of Insomnia about a year and a half ago. Its purpose in life is to make it easy for anyone to temporarily prevent their computer from going to sleep without having to futz with system-wide power options every time. Insomnia did its job well and people used it in ways I didn't expect: there were requests to allow the window to be minimized to the notification area, so I posted an update a few months later which allowed that. As a result, some people leave Insomnia running for extended periods of time (e.g., many days) and seemed likely to benefit from a version that didn't include the overhead of the .NET Framework, so I created new, native-code 32- and 64-bit versions of Insomnia late last year. These new versions did exactly what they were intended to and were also well received - but there's a catch...

Every couple of weeks or so, Insomnia gets featured by one of those "cool app of the day" sites (which is awesome, so thanks for that!). I never know when it's going to happen, but I can tell exactly when it does because I suddenly get a flurry of comments telling me the native-code versions don't run on Windows XP...

Aside: Many of you may be too young to remember; Windows XP is an operating system Microsoft released about ten years ago - practically an eternity in computing terms! And yet, a lot of people are still running XP... ;)

 

Although I didn't set out to not support Windows XP, I also didn't make a specific effort to support it - and as the saying goes, "if you don't test it, it won't work". Well it didn't work, so I investigated and summarized my findings in a reply on my blog:

I've looked into the Windows XP (SP3) issue just now - the "ordinal 380" error is due to the fact that the LoadIconMetric API isn't supported on OSes prior to Windows Vista. It's easy enough to use the more general LoadIcon API and then native Insomnia starts successfully on XP - but it doesn't show any text. The missing text is because the LM_GETIDEALSIZE message isn't supported prior to Vista, either - and in this case the simpler LM_GETIDEALHEIGHT message isn't a direct substitute. What's more, the current icon doesn't seem to be recognized by XP, either (it shows the generic application icon in Explorer and nothing in the tray). Neither of these issues (text measurement and icon) are overly difficult to fix, but they're also not trivial and I'm not sure how worthwhile it is to spend time and effort to support native Insomnia on Windows XP when the .NET version is reported to work just fine...

That said, I'm open to input here. If a lot of people think this is useful, I'll look into doing the work - but if everyone's happy to use the .NET version on XP, I'm happy to let them. :)

For what it's worth, I don't recall anybody coming back with a compelling reason why XP support is necessary - but after getting another round of XP feedback recently, I decided it was something I should do simply because it comes up so often. Therefore, I'm happy to announce that Insomnia's native 32-bit and 64-bit versions now support Windows XP!

Insomnia running on Windows XP

 

Note: With today's update (and in lieu of feedback to the contrary), the native versions of Insomnia are believed to run everywhere the .NET version does. Because there's no functional difference between the native- and managed-code implementations, I'll probably deprecate the .NET version soon. (Please don't get me wrong: I love the significant productivity benefits of using .NET! They're just moot here because I'm already doing the work to maintain the native implementations.)

 

Notes:

  • By far the biggest change with this release is the replacement of the SysLink control with one I wrote called IdealSizeStatic. Recall from the previous post that there were two things I liked about SysLink: its ability to return an "ideal size" and its ability to render hyperlinks. Both of these features worked like I wanted, but the lack of support for LM_GETIDEALSIZE on XP was a deal-breaker. When creating IdealSizeStatic, I kept things as simple as possible while also being consistent with how SysLink operates (ex: the use of WM_CTLCOLORSTATIC and WM_SETFONT) just in case I decide to switch back some day. IdealSizeStatic ends up being a pretty general-purpose control that offers WM_GETIDEALSIZE for querying the bounds (width and height) of its text - which is handy for the WPF-like layout pass I implemented in Insomnia.

    Despite my goal of keeping IdealSizeStatic as simple as possible, I didn't want to give up on the hyperlink functionality Insomnia already used, so I did the work to support that scenario. Specifically, if the first character of its window title is '_', IdealSizeStatic assumes it's showing a link, strips off the '_' prefix, and renders the control text in blue. Assuming WS_TABSTOP has also been set, it will show a focus rectangle when relevant and respond to mouse left-button clicks and space bar presses by calling ShellExecuteEx to open the link in the user's preferred web browser.

    IdealSizeStatic won't win any awards for "Win32 control of the year", but it seems to do just enough to be an adequate replacement for SysLink. :)

  • Having purged the SysLink control, Insomnia no longer has a dependency on the COMCTL32 common control DLL and the corresponding code to initialize it and incorporate the necessary manifest has been removed.

  • The other problem with running on XP was the use of the LoadIconMetric API to retrieve the application icon for the notification area. Fortunately, it's pretty simple to fall back to the LoadImage API instead - though it doesn't offer the same "auto-scaling" magic the original function does.

  • Speaking of icons, one curious problem with XP was that Windows Explorer showed the default application icon instead of the custom one embedded in the Insomnia executable. This ends up being because the custom ICO file generator I wrote/use outputs icon images in the 32-bit alpha-blended PNG format and that format isn't supported on Windows XP. This time around, I've also embedded 16x16 and 32x32 icons with the older 24-bit image+mask format. Because this type is recognized by XP, the icon shows up correctly.

    Aside: Unfortunately, XP still has a bit of trouble rendering the bottom-most pixels of the 32x32 icon in the application's property page. But that property page seems to have a variety of troubles with icons - there was a similar issue with the previous version even under Windows 7!
  • I've also fixed a couple of minor issues I noticed along the way - none of which should matter much in practice. The new version of the 32-bit and 64-bit builds of Insomnia is 2011-03-19. The version number of the .NET build has not changed and remains 2010-01-29.

 

[Click here to download the 32-bit, 64-bit, and .NET builds of Insomnia along with the complete source code for everything.]

 

I initially put off supporting XP because I figured very few people still used it. However, the steady stream of feedback from XP users finally convinced me there's enough interest to make the effort worthwhile. Windows 7 and Windows Vista users won't see functional differences with this release, but they will benefit from the slightly reduced footprint that comes from breaking the ties to COMCTL32.dll. My IdealSizeStatic control isn't a perfect replacement for the SysLink control, but it gets close enough - and does so without being overly complex.

Windows XP users: I hope you like the new support. Thanks for your patience! :)

MEF lab [How to: Keep implementation details out of a MEF contract assembly by implementing an interface-based event handler]

In the previous post, I showed how to combine .NET 4's "type embedding" capability with the Managed Extensibility Framework (MEF) to create an application that can be upgraded without breaking existing extensions. In that post, I described the notion of a MEF "contract assembly" thusly:

The contract assembly is the place where the public interfaces of an application live. Because interfaces are generally the only thing in a contract assembly, both the application and its extensions can reference it and it can be published as part of an SDK without needing to include implementation details, too.

The idea is pretty straightforward: an application's public API should be constant even if the underlying implementation changes dramatically. Similarly, the act of servicing an application (e.g., patching it, fixing bugs, etc.) should never require updates to its public contract assembly.

 

Fortunately it's pretty easy to ensure a contract assembly contains only interfaces and .NET Framework classes (which are safe because they're automatically versioned for you). But things get a little tricky when you decide to expose a custom event...

Imagine your application defines an event that needs to pass specific information in its EventArgs. The first thing you'd do is create a subclass - something like MyEventArgs - and store the custom data there. Because the custom event is part of a public interface, it's part of the contract assembly - and because the contract assembly is always self-contained, the definition of MyEventArgs needs to be in there as well. However, while MyEventArgs is probably quite simple, its implementation is... um... an implementation detail [ :) ] and does not belong in the contract assembly.

Okay, no problem, create an IMyEventArgs interface for the custom properties/methods (which is perfectly acceptable for a contract assembly) and then add something like the following to the application (or an extension):

class MyEventArgs : EventArgs, IMyEventArgs

The public interface (in the contract assembly) only needs to expose the following and all will be well:

event EventHandler<IMyEventArgs> MyEvent;

Oops, sorry! No can do:

The type 'IMyEventArgs' cannot be used as type parameter 'TEventArgs' in
the generic type or method 'System.EventHandler<TEventArgs>'. There is no
implicit reference conversion from 'IMyEventArgs' to 'System.EventArgs'.

 

The compiler is complaining there's no way for it to know that an arbitrary implementation of IMyEventArgs can always be converted to an EventArgs instance (which is what the TEventArgs generic type parameter of EventHandler<TEventArgs> is constrained to). Because there's not an obvious way to resolve this ambiguity (the implicit keyword doesn't help because "user-defined conversions to or from an interface are not allowed"), you might be tempted to move the definition of MyEventArgs into the contract assembly and pass that for TEventArgs instead. That will certainly work (and it's not the worst thing in the world) but it feels like there ought to be a better way...

And there is! Instead of using a new-fangled generic event handler, we could instead use a classic .NET 1.0-style delegate in our contract assembly:

/// <summary>
/// Interface for extensions to MyApplication.
/// </summary>
public interface IMyContract
{
    /// <summary>
    /// Simple method.
    /// </summary>
    void MyMethod();

    /// <summary>
    /// Simple event with custom interface-based EventArgs.
    /// </summary>
    event MyEventHandler MyEvent;
}

/// <summary>
/// Delegate for events of type IMyEventArgs.
/// </summary>
/// <param name="o">Event source.</param>
/// <param name="e">Event arguments.</param>
public delegate void MyEventHandler(object o, IMyEventArgs e);

/// <summary>
/// Interface for custom EventArgs.
/// </summary>
public interface IMyEventArgs
{
    /// <summary>
    /// Simple property.
    /// </summary>
    string Message { get; }
}

With this approach, the contract assembly no longer needs to include the concrete MyEventArgs implementation: the delegate above is strongly-typed and doesn't have the same constraint as EventHandler<TEventArgs>, so it works great! With that in place, the implementation details of the MyEventArgs class can be safely hidden inside the extension (or application) assembly like so:

/// <summary>
/// Implementation of a custom extension for MyApplication.
/// </summary>
[Export(typeof(IMyContract))]
public class MyExtension : IMyContract
{
    /// <summary>
    /// Simple method outputs the extension's name and invokes its event.
    /// </summary>
    public void MyMethod()
    {
        Console.WriteLine("MyExtension.MyMethod");
        var handler = MyEvent;
        if (null != handler)
        {
            handler(this, new MyEventArgs("MyEventArgs"));
        }
    }

    /// <summary>
    /// Simple event.
    /// </summary>
    public event MyEventHandler MyEvent;
}

/// <summary>
/// Implementation of a custom interface-based EventArgs.
/// </summary>
class MyEventArgs : EventArgs, IMyEventArgs
{
    /// <summary>
    /// Simple property.
    /// </summary>
    public string Message { get; private set; }

    /// <summary>
    /// Initializes a new instance of the MyEventArgs class.
    /// </summary>
    /// <param name="message">Property value.</param>
    public MyEventArgs(string message)
    {
        Message = message;
    }
}

 

The sample application I've created to demonstrate this practice in action (a simple executable/contract assembly/extension assembly trio) is quite simple and works just as you'd expect. Here's the output:

MyApplication.Run
MyExtension.MyMethod
MyEventArgs

 

[Click here to download the complete source code for the MefContractTricks sample.]

 

Keeping a MEF application's contract assemblies as pure and implementation-free as possible is a good and noble goal. There may be times when it is necessary to make compromises and allow implementation details to sneak into the contract assembly, but the use of custom event arguments does not need to be one of them!

So instead of being generic - and failing - go retro for the win! :)

MEF addict [Combining .NET 4's type embedding and MEF to enable a smooth upgrade story for applications and their extensions]

One of the neat new features in version 4 of the .NET Framework is something called "type equivalence" or "type embedding". The basic idea is to embed at compile time all the type information about a particular reference assembly into a dependent assembly. Once this is done, the resulting assembly no longer maintains a reference to the other assembly, so it does not need to be present at run time. You can read more about type embedding in the MSDN article Type Equivalence and Embedded Interop Types.

Although type equivalence was originally meant for use with COM to make it easier to work against multiple versions of a native assembly, it can be used successfully without involving COM at all! The MSDN article Walkthrough: Embedding Types from Managed Assemblies (C# and Visual Basic) explains more about the requirements for this along with explicit steps to use type embedding with an assembly.

 

Here's a simple interface that is enabled for type embedding:

using System.Runtime.InteropServices;

[assembly:ImportedFromTypeLib("")]

namespace MyNamespace
{
    [ComImport, Guid("1F9BD720-DFB3-4698-A3DC-05E40EDC69F1")]
    public interface MyInterface
    {
        string Name { get; }
        string GetVersion();
    }
}

 

Another thing that's new with .NET 4 (though it had previously been available on CodePlex) is the Managed Extensibility Framework (MEF). MEF makes it easy to implement a "plug-in" architecture for applications where assemblies are loosely coupled and can be added or removed without explicit configuration. While there have been a variety of not-so-successful attempts to create a viable extensibility framework before this, there's general agreement that MEF is a good solution and it's already being used by prominent applications like Visual Studio.

 

Here's a simple MEF-enabled extension that implements - and exports - the interface above:

[Export(typeof(MyInterface))]
public class MyExtension : MyInterface
{
    public string Name
    {
        get { return "MyExtension"; }
    }

    ...
}

And here's a simple MEF-enabled application that uses that extension by importing its interface:

class MyApplication
{
    [ImportMany(typeof(MyInterface))]
    private IEnumerable<MyInterface> Extensions { get; set; }

    public MyApplication()
    {
        var catalog = new DirectoryCatalog(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
        var container = new CompositionContainer(catalog);
        container.SatisfyImportsOnce(this);
    }

    private void Run()
    {
        Console.WriteLine("Application: Version={0}", Assembly.GetEntryAssembly().GetName().Version.ToString());
        foreach (var extension in Extensions)
        {
            Console.WriteLine("Extension: Name={0} Version={1}", extension.Name, extension.GetVersion());
        }
    }

    ...
}

 

The resulting behavior is just what you'd expect:

P:\MefAndTypeEmbedding>Demo

Building...
Staging V1...
Running V1 scenario...

Application: Version=1.0.0.0
Extension: Name=MyExtension Version=1.0.0.0

...

 

However, it's important to note that MEF does not isolate an application from versioning issues! Ideally, extensions written for version 1 of an application will automatically load and run under version 2 of that application without needing to be recompiled - but you don't get that for free. There is an easy way to do this, though: avoid making any changes to the contract assembly after v1 is released. :)

Aside: The contract assembly is the place where the public interfaces of an application live. Because interfaces are generally the only thing in a contract assembly, both the application and its extensions can reference it and it can be published as part of an SDK without needing to include implementation details, too.

But because the whole point of version 2 is to improve upon version 1, it's quite likely the contract assembly will undergo some changes along the way. This is where problems come up: assuming the contract assembly was strongly-named and its assembly version updated (as it should be if its contents have changed!), v1 extensions will not load for the v2 application because they won't be able to find the same version of the contract assembly they were compiled against...

Aside: If the contract assembly was not strongly-named, then v1 extensions might be able to load the v2 version - but it won't be what they're expecting and that can lead to problems.

 

Here's an updated version of the original interface with a new Author property for version 2:

using System.Runtime.InteropServices;

[assembly:ImportedFromTypeLib("")]

namespace MyNamespace
{
    [ComImport, Guid("1F9BD720-DFB3-4698-A3DC-05E40EDC69F1")]
    public interface MyInterface
    {
        string Name { get; }
        string GetVersion();
        string Author { get; }
    }
}

 

One way to solve the versioning problem is to ship the v1 contract assembly and the v2 contract assembly along with the v2 application. (Of course, this can be tricky if both assemblies have the same file name, so you'll probably also want to name them uniquely.) Shipping multiple versions of a contract assembly works well enough (it's pretty typical for COM components), but it can also cause some confusion for Visual Studio when it sees multiple same-named interfaces referenced by the v2 application - not to mention the developer burden of managing multiple distinct versions of the "same" interface...

Fortunately, there's another way that doesn't require the v2 application to include the v1 contract assembly at all: type embedding. If the contract assembly is enabled for type embedding and v1 extension authors enable that when compiling, all the relevant bits of the contract assembly will be included with the v1 extension and there will be no need for the v1 contract assembly to be present. What that means is "reasonable" interface changes during development of the v2 application will automatically be handled by .NET and v1 extensions will work properly without any need to recompile/upgrade/etc.!

Aside: By "reasonable" interface changes, I mean removing properties or methods (and therefore not calling the v1 implementations) or adding them (which will throw MissingMethodException for v1 extensions that don't support the new property/method). Changes to existing properties and methods are trickier and probably best avoided as a general rule.

 

The v2 version of the sample application uses the Author property when it's present (for v2 extensions), but gracefully handles the case where it's not (as for v1 extensions):

private void Run()
{
    Console.WriteLine("Application: Version={0}", Assembly.GetEntryAssembly().GetName().Version.ToString());
    foreach (var extension in Extensions)
    {
        string author;
        try
        {
            author = extension.Author;
        }
        catch (MissingMethodException)
        {
            author = "[Undefined]";
        }
        Console.WriteLine("Extension: Name={0} Version={1} Author={2}", extension.Name, extension.GetVersion(), author);
    }
}

 

Here's the v2 version in action:

...

Staging V2...
Running V2 scenario...

Application: Version=2.0.0.0
Extension: Name=MyExtension Version=1.0.0.0 Author=[Undefined]
Extension: Name=MyExtension Version=2.0.0.0 Author=Me

 

[Click here to download the complete source code for the sample application/contract assembly/extensions and demo script used here.]

 

Type embedding and MEF are both fairly simple concepts that add a layer of flexibility to enable some pretty powerful scenarios. As is sometimes the case, the whole is greater than the sum of its parts and combining these two technologies provides an elegant solution to the tricky problem of upgrading an application without breaking existing plug-ins.

If you aren't already familiar with MEF or type embedding, maybe now is a good time to learn! :)

 

PS - My thanks go out to Kevin Ransom on the CLR team for providing feedback on a draft of this post. (Of course, any errors are entirely my own!)