Mad Props!

Omniscience is just a Google-search away.

Login

You're reading Mabsterama, the weblog of Matt Hamilton. Enjoy your stay.

AWDNUG December 2008

Last night’s meeting of the Albury/Wodonga .NET User Group was one of the best we’ve had for a while. Although we still aren’t getting the numbers we’d like (there were seven of us this time around), we got a great presentation from relative-newcomer Nathan on InfoPath.

Nathan ran through the basics of InfoPath and knocked up a demo form that submitted its data at first by writing to an Access database and then later by emailing an xml file to a preconfigured address. We discussed the various uses that InfoPath might play in an organization, particularly around the offline submission of forms which could be queued in your Outlook outbox until you reconnected.

Here at work we’ve been using simple SharePoint forms coupled with Nintex Workflow to do some of our form-submissions stuff, but I can see a future for InfoPath for us. The only obstacle might be licensing, given that the client application is only available in the Pro SKU of Office 2007 (as far as I know), or if you want to use the server component to render your forms in the browser there’s another cost there. Still, you never know!

We’re taking January off as is our custom, but we’ll be back on the second Tuesday of February 2009 with an as-yet-undisclosed presentation from Anton, which I’m sure will rock the house. If you’re one of the 20-or-so people that are on the mailing list but don’t show, please consider coming along! The more the merrier!

String Formatting with Named Parameters

Remember a few posts ago when I was suggesting that we should be able to use named parameters in C# 4.0 in the same way that we use the “params” keyword right now? I was thinking that we could declare a method like this:

void Foo(params IDictionary<string, object> items);

… and then call it like this:

Foo(fizz: 1, buzz: "hello");

So our “items” dictionary now contains two key/value pairs: {“fizz”, 1} and {“buzz”, “hello”}.

I don’t know why it didn’t occur to me at the time, but I realise now that this syntax would be really handy for string formatting. Instead of the current String.Format method’s dependence on the order of the parameters, it could be keyword based. Imagine an extension method like this:

string Format(this string s, string format, params IDictionary<string, object> args);

Now we can format our strings using this syntax:

return String.Format("{name} - {dob}", name: "Matt", dob: new DateTime(1973, 3, 22));
Isn’t that a bit more intuitive than the “{0} - {1}” format strings you’re used to? I think a “named params” feature like this would be really handy.

Demonstrating MEF

I watched Glenn Block’s demonstration of the Managed Extensibility Framework on dnrTV last night, and came away wondering why the demo didn’t “work”. I’m a big fan of MEF, and I could see what Glenn was doing, but you could tell that Carl didn’t quite grok it.

So I started thinking about the things that didn’t work in the dnrTV episode and how I would demo MEF to an audience that had never heard of it.

1. Don’t use the Program class

Applications that use MEF need an instance of a class to act as the “host” for imported objects. That’s fine for WPF applications, because they have a little baked-in class called App that gets created when the application runs. That means you can just add the instance of your App class to the CompositionContainer and it’ll work.

For console applications, though, there is no class that’s instantiated when the application runs. The whole thing happens from a static method called “Main” in your “Program” class. That means that if you want to use MEF, you have to either create a whole new class and use an instance of that, or (easier to do in demos) create an instance of the Program class. The problem, of course, is that as soon as someone sees this code:

class Program
{
    static void Main(string[] args)
    {
        var p = new Program();
        p.DoStuff();
    }

… they get confused. “New program?” asked Carl on dnrTV. I can understand why. Why new up a Program instance when we’re in a static method?

Glenn has explained to me that console applications are the best way to demonstrate MEF, because they prove that it’s a “client-agnostic” framework. If you use WPF to demonstrate it then there’s a risk that your audience will think it’s something that only works with WPF. So by all means use a console application, but rip out the MEF bits and put them into a different class (for example, “MyMefApplication”). Then change your Main method so that it looks more like this:

class Program
{
    static void Main(string[] args)
    {
        var app = new MyMefApplication();
        app.DoStuff();
    }
}

The same holds true for Windows Forms to a lesser degree. It, too, all starts with a static Main method in a Program class. You can, however, get away with just using the main form in a WinForms app as your MEF host.

2. Start with DirectoryPartCatalog

When people think of extensibility, they immediately think of plug-ins, in the form of assemblies that a user can drop into a folder to extend an application. Certainly that’s what Carl was thinking when the MEF demonstration began. However, the easiest way to demonstrate MEF is to use an AttributedAssemblyPartCatalog and point it either at the current assembly or an assembly you’ve added a reference to. For a newbie, this is quite confusing. Why use MEF at all if you have to add a reference to the “plug-in” assembly?

Of course, there are lots of reasons why you’d use an AttributedAssemblyPartCatalog and point it at either the current assembly or a known, referenced assembly. For example, you might want to provide some “default” extensions. Comicster’s doing that at the moment in my test code – it provides a couple of default file formats as well as letting the user develop their own. So I add my own “default file formats” assembly to an AggregatingComposablePartCatalog, and then add a DirectoryPartCatalog for user-created file formats.

Having said that; starting with extensions in the same assembly (or one that you’ve explicitly referenced) is just too darn confusing for newcomers. Always make your first demo one that looks for files in a folder.

3. Make extensions that have some visible side-effect

One of the most confusing thing about the dnrTV demonstration was the fact that Glenn’s extension class (a “Reverb” class that implemented IEffect) didn’t actually do anything. Following Carl’s suggestion, he gave it a single method that accepted a byte array and returned a byte array. Since the extension didn’t provide any useful visual feedback, the only way Glenn could demonstrate that it was being loaded was by printing the count of his “Effects” collection at runtime. If the count was 0, no extensions were available. If it was 1, the “Reverb” extension had been imported.

This made for a pretty dry demo. If you want to really show the user that your extension has been loaded, make it throw something up on the screen. It might add a MenuItem to your form’s main menu, or it might call MessageBox.Show() to display a message. That way you can invoke the method and prove conclusively that the extension has been imported.

4. Don’t do anything too tricky up front

This kind of ties in with the first step in this post. Because Glenn was working with a “Program” class as his “host” instance, he got tricky. He used MEF itself to provide him with an instance of the class. That’s inspired and very cool, it’s confusing for people who are new to the concept of imports and exports. Carl was confused enough by the need to create an instance of the Program class in the first place, but this just took it to the next level.

Some of the MEF sample applications do some very nifty stuff like importing the main window of the app, so that any imports that need to be satisfied on that window can be done so without having to add that instance to the CompositionContainer. Again, this is a really neat trick, but try to find a way around it when you’re first demonstrating the framework. You’re just gonna freak people out.

5. MEF Rocks

I just want to reiterate that MEF is a really cool technology and you shouldn’t be scared of it. I don’t want this post to sound like I’m ripping on Glenn’s demo: everything he showed made sense to me as someone who has already sipped from the MEF kool-aid cup, and he was constrained by the example that Carl had offered up. Hopefully others might get some ideas from this post for their inevitable MEF demo at the local user group.

File Format Plug-Ins with MEF

So last night I implemented the ideas from my last post, in that I turned my ICollectionWriter interface into an ICollectionReaderWriter interface, and derived it from ICollectionReader. So now if you want to create a class that can write a collection to a stream, you’re forced to also implement the ability to read it back in[1]. This’ll stop people from accidentally saving their work to a file that Comicster can’t open – something that would aggravate new users.

While refactoring the code, I learned a whole lot more about MEF. Let me explain with some code.

In my Comicster.IO.dll assembly, I define two classes (PackageCollectionReader and XmlCollectionReader), which serve as the “default” file formats for Comicster. I “export” them using this MEF attribute:

[Export(typeof(ICollectionReaderWriter))]
public class PackageCollectionReaderWriter : ICollectionReaderWriter
{
    ...
}

Then at the top of my main window’s class I have two properties which get automatically populated by MEF. They import the classes they need using the interface types, like this:

[Import]
public static IList<ICollectionReader> CollectionReaders
{
    get; set;
}

[Import]
public static IList<ICollectionReaderWriter> CollectionReaderWriters
{
    get; set;
}

So because CollectionReaders is an IList of ICollectionReader, MEF knows to go find all the classes that implement ICollectionReader and fill the list with them. Likewise with CollectionReaderWriters.

Here’s where it gets a bit tricky.

Even though ICollectionReaderWriter derives from ICollectionReader, MEF won’t import my PackageCollectionReaderWriter class into the “CollectionReaders” property. The importing procedure is very tightly bound to the specified type, and doesn’t look at ancestor types at all. I can see why – how far up the ancestral tree do you go? You would eventually work your way back to System.Object which would mean that anything could be imported.

Still, I was interested in looking at the MEF source code to see if I could determine how MEF discovers the classes based on their type. In the spirit of Scott Hanselman’s Weekly Source Code, I went spelunking.

It turns out MEF’s exporting and importing is fundamentally based on strings. Each export is given a string to identify it, and imports look for exported types with a matching string. When you supply an [Export] attribute with a type (as I have done above), MEF simply calls ToString() on the type and assigns that to the export. So this line:

[Export(typeof(ICollectionReaderWriter))]

… is fundamentally the same as this:

[Export("Comicster.IO.ICollectionReaderWriter")]

All of a sudden it becomes crystal clear why MEF doesn’t discover types based on their inheritance hierarchy – by the time MEF does its lookups, they’re no longer types: they’re just strings.

So how did I get around the problem of my ICollectionReaderWriter classes not being treated as ICollectionReaders? Well, in the end I worked around it by combining the two lists with a little LINQ statement when I needed them:

var allReaders = CollectionReaderWriters.Cast<ICollectionReader>().Concat(CollectionReaders);

It was a bit of fun trawling through the MEF source, and it’s a testament to the developers that a nincompoop such as myself is able to understand what they’re doing under the hood. Look for more MEF posts in the future as I start to use it in more places!

[1] Ok, I know that nobody is ever forced to correctly implement an interface. There’s nothing stopping you from throwing a NotImplementedException or simply returning null. There’s not a whole lot I can do about that, but this is mostly about guiding the plug-in authors in the right direction rather than imposing rules.

The Perils of Write-Only File Formats

So last night I downloaded the new Preview 3 release of MEF and incorporated into Comicster (you can read the posts leading up to this here and here). Right now I can run Comicster and see “.cmxx” files and “.xml” files in the Open File dialog. if I then close the program and drop a DLL into the “My Documents\Comicster” folder, the next time I run Comicster I see “.cmx” files in the dialog as well. It works a treat and I’ll devote a post to the implementation soon (I don’t have the source handy here at work).

As you saw in my previous posts on the topic, I have defined the “file format plug-in” system using two interfaces, ICollectionReader and ICollectionWriter. That lets me create a “read-only” format to provide migration paths from earlier versions of Comicster or from other programs. The problem, though, is that it also lets people create “write-only” formats. For example, someone might define a “.csv” writer but not an equivalent reader.

Why is this a problem? I’m worried that Joe User might download Comicster for the first time, along with some file-format plug-ins, and spend a few hours creating his collection only to save it as “joe.csv”. He knows he has saved it, but doesn’t realise that he can’t re-open the file, and has essentially lost his work.

The way I’ll address this is slightly rearrange my interfaces so that ICollectionWriter descends from ICollectionReader. That means that if you want to implement a read-only file format you can just implement ICollectionReader, but if you want to implement a format that you can save to, you have to provide a way to read the collection back from that file. I might end up having to rename the ICollectionWriter interface to be more explicit in the fact that it’s both a writer and a reader.

But what, you ask, about exporting a collection to a file format that you don’t plan on reading from? A CSV export, for example, would be quite handy. I’ve got that base covered (at least in my head). I’ll be defining an ICollectionExporter interface, like this:

public interface ICollectionExporter
{
    public void ExportCollection(Collection collection, DirectoryInfo folder);
}
Notice that this interface accepts a DirectoryInfo parameter rather than a Stream to write to. That’s because I want to be able to export into a folder and let the plug-in writer decide whether it’s a single-file export (like CSV) or a multiple-file export (like a series of HTML files). Heck, I might even define two different interfaces so that there’s a choice of exporting to a file or a folder, depending on the plug-in. Then I can surface these exporters under an “Export” button, which will make it much more obvious to Joe User that he’s writing his collection to a format that Comicster may not be able to read.

WPF TextBox SelectAll on Focus

The title of this post is almost pure Google-juice, because this is a trick that I had to relearn on the weekend after a series of unsuccessful searches on the topic.

A behaviour in Windows that most of us are fairly accustomed to (whether we realise it or not) is that upon entering a TextBox, the text is automatically selected. This means that you can tab into a TextBox and then start typing, and whatever was already in there will be automatically overwritten.

In WPF, this behaviour is not present. When you tab into a TextBox your cursor sits at the beginning of the text, and when you start typing, your new text is simply inserted at the beginning. This is really weird for someone who’s used to the “select all on focus” behaviour, and time-consuming for a beginner (who inevitably uses their right-arrow key to scroll to the end of the text, and backspaces to erase it all).

So how do you go about getting this behaviour back? Your first instinct might be to simply catch the GotFocus event on each TextBox and call the SelectAll() method, but that’ll get pretty old by about the thirtieth time you’ve done it. Instead, here’s a simple way to register a global event handler that works on any TextBox in your application:

First, open up your App.xaml.cs file. That’s the file in a WPF project that serves as the entry point for your application. The “App” class has an overridable method called “OnStartup” from which we’ll register our event handler:

protected override void OnStartup(StartupEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),
        TextBox.GotFocusEvent,
        new RoutedEventHandler(TextBox_GotFocus));

    base.OnStartup(e);
}

So I’m using the EventManager class to register a global event handler (not to be confused with Evan Handler) against a type (TextBox)! Pretty neat, huh? The actual handler is dead simple:

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    (sender as TextBox).SelectAll();
}

As you’d expect, we’re selecting the text in the supplied TextBox.

You can read more about class-handling of events on MSDN.

Mapping CLR Namespaces to XML for XAML

In my work on a WPF version of Comicster, I have a few assemblies that I want to reference from my XAML. For example, the Comicster.Core framework assembly (whose CLR namespace is simply “Comicster”) contains the collection classes such as Title, Issue, Character and Creator. The Comicster.Windows.Core assembly (which contains namespaces under “Comicster.Windows”) contains the WPF-specific bits like a thumbnail control, custom RoutedUICommands and IValueConverter implementations.

I soon got tired of mapping the various CLR namespaces to XML namespaces using this construct:

xmlns:c="clr-namespace:Comicster;assembly=Comicster.Core"

It works, but it just doesn’t feel like XAML, especially when you find this just above that in the same XAML file:

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

That’s the sort of thing I wanted to do. So, after a bit of reading, I discovered the XmlnsDefinitionAttribute. You can decorate your assembly with this attribute, and it essentially maps a URI-based XML namespace to your CLR namespace! Just add this to your AssemblyInfo.cs file:

[assembly: XmlnsDefinition("http://comicster.net/2008", "Comicster")]

Now my Comicster namespace (in Comicster.Core.dll) maps nicely to the given URI (which doesn’t have to be a proper resource on the net), and I can replace that namespace declaration at the top of this post with this:

xmlns:c="http://comicster.net/2008"

So that’s just dandy, but there was one last thing bugging me. In my Comicster.Windows.Core assembly, I have a whole slew of namespaces. Comicster.Windows.Converters, Comicster.Windows.Controls, Comicster.Windows.Input etc. I didn’t want all of those namespaces to map to their own URI (and therefore have to have individual xmlns declarations in my XAML file), I wanted them all to get lumped under the same URI like the “x” namespace that maps to the WinFX schema above. I was this close to posting a question on Stack Overflow to ask how to do it, when I thought I’d try this:

[assembly: XmlnsDefinition("http://comicster.net/2008/windows", "Comicster.Windows.Controls")]
[assembly: XmlnsDefinition("http://comicster.net/2008/windows", "Comicster.Windows.Converters")]
[assembly: XmlnsDefinition("http://comicster.net/2008/windows", "Comicster.Windows.Input")]
And guess what? It worked! It turns out that you can just merge all your CLR namespaces into one easy-to-use XML namespace like that. This makes it very easy to code up a “framework” that others can use without having to remember where all the bits live. In a lot of ways, the old adage that applied to NetHack applies to the .NET Framework: “The devteam thinks of everything!”

Named Parameters in C# 4.0

For those who haven’t been keeping score of what’s new in the upcoming C# 4.0 release, one of the features that people are quite chuffed about is named parameters. They essentially let you call a method by naming the parameters for which you would like to specify a value, and the ones you omit get a default value. It looks kind of like this:

DoStuff(foo: "hello", bar: "world", answer: 42);

Thinking about named parameters has me wondering: One of the tricks people have started using in C# 3.0 is to make use of anonymous types to provide a sort of “dynamic parameters” feature. I do it in my AddInputParameters extension method, and the ASP.NET MVC team do it to define routes. This example taken from Phil Haack’s blog:

routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" });

 

See that third parameter? It’s an anonymous type that the MapRoute method can parse into a sort of map (“controller” maps to “Home”, “action” maps to “Index” etc).

What would be nice is if we could use the named parameters syntax to call methods like this. We could effectively omit the “new {}” part of the call:

routes.MapRoute("Default", "{controller}/{action}/{id}", controller: "Home", action: "Index", id: "");

I don’t know how such a method would be declared, but the syntax reminds me of the “params” keyword, where you can tell your method that the last parameter is an array of unknown length and can be passed as arbitrary parameters. So perhaps something like:

void MapRoute(string name, string path, params IDictionary<string, object> maps);

So now that last parameter would seamlessly pass our named parameter list into the “maps” dictionary.

What do you think? Anything that removes a bit of extra punctuation from the code would have to be helpful.

AWDNUG November 2008

Last night's meeting of the Albury/Wodonga .NET User Group was almost a write-off. With nobody putting their hand up to present, we had no fixed agenda. With one or two notable exceptions, it has basically fallen on myself, Andrew or Anthony to present every month for the past, I don't know, year's worth of meetings. I honestly love presenting and would do it every month, but I think someone else should be willing to have a go, if only to break the mabsteropoly.

Anyway, only four of us showed up, but we huddled around my laptop and had a first look at the Managed Extensibility Framework preview, which I had downloaded only an hour earlier. We put together a Windows Forms application which watched a folder for new "plug-ins", and when you clicked a button it displayed a message generated from those plug-in assemblies. A very simplistic demo, but I'm really impressed with how easy MEF makes it! I don't know how much impact MEF will have on our run-of-the-mill line-of-business applications here at work, but for other projects like Comicster I think it has a big future.

Next month Nathan (the "new guy" until someone newer shows up) has volunteered to present. The presentation itself is a surprise at this stage (I'm not sure even Nathan knows), but when I suggested that he do a presentation on building an enterprise data entry application using Lisp, he told me that he could instead do it with a lisp. Now that I'd like to see!

LINQ with Reflection Part 2

I've taken the code in my last post to the next level!

As you recall, I have two interfaces (ICollectionReader and ICollectionWriter) and I have some code (with a very funky LINQ query) to find all the classes in an assembly that implement one of those interfaces and return me a list of instances of them.

I found this evening that this code was almost, but not quite, identical for readers and writers, so I managed to construct a generic method that encompasses both! Here's the method:

private static IEnumerable<T> InstancesOf<T>() where T : class
{
    var type = typeof(T);
    return from t in type.Assembly.GetExportedTypes()
           where t.IsClass
               && type.IsAssignableFrom(t)
               && t.GetConstructor(new Type[0]) != null
           select (T)Activator.CreateInstance(t);
}

So this method is very similar to the query from my previous post, but it works generically so I can call it for either interface! Now I have this code in my main form's constructor:

CollectionReaders = InstancesOf<ICollectionReader>().ToList();

CollectionWriters = InstancesOf<ICollectionWriter>().ToList();

How clean is that? That pre-populates two properties with all the available classes that implement ICollectionReader and ICollectionWriter respectively! Easy to read and (as an added bonus) a step towards the inevitable MEF implementation!