Monday, November 23, 2009

Playing Nice with Other Assemblies using MEF Catalogs

Looking over the previous three posts, we have been working within a single assembly for managing our extensibility parts.  While this works well if we want to use MEF more as an IoC container, it really limits the extensibility of our application.  In the single assembly model that we've been using, every update would require a new build of the application.  To overcome this limitation, we'll create a new example project that builds on what we've covered and branch it out into multiple assemblies.

Building a Console's Help Information

In the new example, we'll be creating a new console application whose sole purpose is to output help documentation on various fake commands.  We aren't going to be implementing any of the actual command functionality; however, each extension will represent a new command and is responsible for its own help documentation.  Given our scenario, it isn't very practical for an application to do nothing without any extensions.  Because of this, our example will be importing in the various parts from both inside of its own assembly (like we've done previously) as well as assemblies located in a Plug-Ins directory.

Defining Our Project Structure

Given the scenario that we are going to be working on, there are a couple of different ways we can structure our solution.  In an attempt to make this a bit more practical, we'll split out our extensibility contract into a separate assembly.  This assembly we'll reference into our hosting application as well as any external plug-in assemblies so that they aren't directly referencing our executable. While this extra assembly that contains our extensibility contract will be very simple, it also provides a point to branch out with other core functionality in a real world scenario.

For the sake of this example, let's start a new Windows Console application project named MEFExample4. Once the solution was created, we need to add a Class Library Project named MEFExample4.Core.  Below is an image of the possible solution explorer window inside of Visual Studio.

Example4-SolutionExplorerStart

Creating Our Extensibility Contract

Now that we have the project structure established, let's go ahead and add a new Interface to the MEFExample4.Core project named IHelp.  This interface will be used by our various "commands" and define a CommandName and HelpText property.  Below is the code for IHelp.

   1:  namespace MEFExample4.Core
   2:  {
   3:      public interface IHelp
   4:      {
   5:          string CommandName { get; }
   6:          string HelpText { get; }
   7:      }
   8:  }

Building the Hosting Application

Now that we have our contract by means of the MEFExample4.Core.IHelp type, let's create our extensible application that imports multiple instances of IHelp types.  In this first iteration, we'll setup the application in the same way as our initial, simple example from earlier posts. We'll use the AssemblyCatalog which is used to instantiate types of a given assembly, and like our previous examples, will use Reflection to get the currently executed assembly. 

In addition to the catalog we're currently choosing, we need to make sure that we have our collection property to hold our imported parts and decorate it with the ImportMany(typeof(IHelp)) attribute. Once that's in place, the only thing left is to setup our console output for displaying the CommandName and HelpText properties of our imports.  Below is first iteration of our Program.cs file.

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.ComponentModel.Composition;
   4:  using System.ComponentModel.Composition.Hosting;
   5:  using System.Reflection;
   6:  using System.Text;
   7:  using MEFExample4.Core;
   8:   
   9:  namespace MEFExample4
  10:  {
  11:      class Program
  12:      {
  13:          static void Main(string[] args)
  14:          {
  15:              Program p = new Program();
  16:              p.Run();
  17:          }
  18:   
  19:          [ImportMany("command", typeof(IHelp))]
  20:          public IEnumerable<IHelp> Commands { get; set; }
  21:   
  22:          void Run()
  23:          {
  24:              Compose();
  25:   
  26:              foreach(IHelp cmd in Commands)
  27:              {
  28:                  Console.WriteLine(FormatCommandOutput(cmd));
  29:              }
  30:   
  31:              Console.ReadKey();
  32:          }
  33:   
  34:          void Compose()
  35:          {
  36:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  37:              var container = new CompositionContainer(catalog);
  38:              container.ComposeParts(this);
  39:          }
  40:   
  41:          string FormatCommandOutput(IHelp command)
  42:          {
  43:              StringBuilder sb = new StringBuilder();
  44:              sb.AppendLine(command.CommandName);
  45:              sb.AppendLine(string.Empty); //empty line
  46:   
  47:              List<string> splitText = SplitText(command.HelpText);
  48:   
  49:              splitText.ForEach(t => sb.AppendLine(t));
  50:   
  51:              return sb.ToString();
  52:          }
  53:   
  54:          List<string> SplitText(string text)
  55:          {
  56:              const int LINE_LENGTH = 55;
  57:              int length = text.Length;
  58:              List<string> output = new List<string>();
  59:   
  60:              for (int i = 0; i * LINE_LENGTH < length; i++)
  61:              {
  62:                  if (i*LINE_LENGTH + LINE_LENGTH <= length)
  63:                  {
  64:                      output.Add(text.Substring(i * LINE_LENGTH, LINE_LENGTH).PadLeft(60, ' '));
  65:                  }
  66:                  else
  67:                  {
  68:                      output.Add(text.Substring(i * LINE_LENGTH).PadLeft(55, ' '));
  69:                  }
  70:              }
  71:   
  72:              return output;
  73:          }
  74:      }
  75:  }

Writing the First Command

Now that we have our contract and hosting application defined, we need to create our first "command".  We started our application to look inside of it's own assembly for our various types that will be imported.  Because of this, we need to add a new class called TestCommand and have it implement our IHelp interface.  Let's set the CommandName property to "Test" and the HelpText property to some random text.  Once we decorate the class with our Export(typeof(IHelp)) attribute, we can compile and run the application and see our text.

Example4-OutputTest1

Preparing the Application For External Plug-ins

We've tested our application in the same fashion as the previous posts in this series and we're almost ready to work with external assemblies.  Before we do that, we need to add a new folder to our console application project named Plug-Ins.  This folder will be our holding area for the external assemblies that house additional "commands". 

The second thing we need to do is change our AssemblyCatalog to a DirectoryCatalog object.  Unlike an AssemblyCatalog which accepts an assembly as a constructor parameter, the DirectoryCatalog accepts a file path (relative or absolute) to the location where any number of the assemblies are found.  In addition to that difference, the DirectoryCatalog will review all assemblies located in the supplied directory.  This means that once we point our DirectoryCatalog to our Plug-Ins folder, we can just start dropping assemblies into there without having to recompile the console app. Note: Since the project uses the default build location of /bin/Debug, the path we supply will traverse up the directory tree once again. In practice, the Plug-Ins directory should probably be in the same directory as the executable application or the path configurable via an App.config file.  Below is the updated Program.Compose() method.

   1:  void Compose()
   2:  {
   3:      var catalog = new DirectoryCatalog(@"..\..\Plug-ins\");
   4:      var container = new CompositionContainer(catalog);
   5:      container.ComposeParts(this);
   6:  }

Adding Another Assembly

With our folder/repository ready to be used by our DirectoryCatalog, it's time for us to create a new "command" that implements IHelp from a new/separate assembly. Let's add a new class library project called MEFExample4.Commands.  Before we write any code for our new command, let's update the project properties a little bit.  Since we are working on our Commands assembly in the same solution as the application, let's add a Post-Build Event script that will copy our built Commands assembly to the Plug-Ins directory we made in the previous section.  To do this, we need to open the Project's Property window and click on the Build Events tab.  In the Post-Build Event Command Line textbox, we need to add the following:

copy $(TargetPath) $(SolutionDir)\MEFExample4\Plug-ins\$(TargetFileName)

If you are not familiar with Pre/Post-Build events and the macros, feel free to check out this link since they can be used to do some pretty interesting things.  As for the above script, it tells the build manager to copy the TargetPath (the built .dll file) and copy it to the application's Plug-ins directory using the same name.

Now that we have the project setup, we can write the code for our next "command".  We are going to rename Class1.cs to ExampleCommand.cs and add the below code into it.

   1:  using System.ComponentModel.Composition;
   2:  using MEFExample4.Core;
   3:   
   4:  namespace MEFExample4.Commands
   5:  {
   6:      [Export("command", typeof(IHelp))]
   7:      public class ExampleCommand : IHelp
   8:      {
   9:          private string _helpText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
  10:                                          "Nulla molestie erat rhoncus sapien volutpat rhoncus sed sit " +
  11:                                          "amet dolor. Aliquam rhoncus sem et neque elementum lacinia ut " +
  12:                                          "vel est. Vestibulum et urna sit amet nibh feugiat imperdiet ac " +
  13:                                          "id tellus. Fusce lectus risus, congue et.";
  14:   
  15:          public string CommandName
  16:          {
  17:              get { return "Example1"; }
  18:          }
  19:   
  20:          public string HelpText
  21:          {
  22:              get { return _helpText; }
  23:          }
  24:      }
  25:  }

After that, let's build the solution and test everything out.  When we run the application we should now see Example1 and the Ipsum text that we designated for the HelpText property like the image below.

Example4-OutputTest2

In addition, if we take a look in the Plug-Ins directory, we can also see our MEFExample4.Commands.dll is listed.

Working with Internal and External Assemblies

Now that we've seen how to work with the currently executing assembly as well a directory containing multiple different assemblies, there's one last thing for this post.  What if we wanted to look both internally and externally for our Commands?  An application like this without any native commands is just a shell and provides little initial value.  Sure we can create all of our commands in a separate assembly so we never have to touch the application; however, this allows for our initial commands to be deleted.  In order to cultivate both internal commands and external commands, we need to use an AggregateCatalog object.

An AggregateCatalog differs from an AssemblyCatalog or a DirectoryCatalog in that it's, in essence, a catalog of catalogs.  Looking at the intellisense, we're shown that the AssemblyCatalog constructor accepts either an IEnumerable<ComposablePartCatalog> object or a parameter array of ComposablePartCatalogs.  For the example, we'll use the parameter array version of the constructor to add new instances of an AssemblyCatalog and DirectoryCatalog into our new AggregateCatalog as shown by the updated code below.

   1:  void Compose()
   2:  {
   3:      var catalog = new AggregateCatalog(new DirectoryCatalog(@"..\..\Plug-ins\"),
   4:                                         new AssemblyCatalog(Assembly.GetExecutingAssembly()));
   5:      var container = new CompositionContainer(catalog);
   6:      container.ComposeParts(this);
   7:  }

Once we do this, we can test the application and see that the output has changed to the following:

Example4-OutputTest3

Summary

In this post we really looked at starting a more applicable console application using MEF.  We looked at how you can use a couple different catalogs in order to obtain the assemblies that contain parts for our application.  There are additional catalogs available that allow other ways to import assemblies and types and can also be used with an AggregateCatalog.  In the next post for this series, we'll dive into how MEF handles Circular References real quick and then further expand our example.

Resources:



kick it on DotNetKicks.comShout it

Thursday, November 19, 2009

LINQing to MEF Imports

At the end of the last post, we looked at how we can explicitly manage our imports and exports using a combination of text-based labels and type declarations.  In addition, we began to look at the ImportMany() attribute for importing more than one value in our extensible application.  Along with the ImportMany(), we looked at looping through the simple example to display the property of each imported type.  This approach isn't bad if the number of imported types are small; however, looping really wouldn't work well if your application loaded a very large amount of applications.  In a way, it's a great problem to have if your application has a large community based plug-in repository (i.e. Wordpress or Firefox).  There may come a time when we may need to find a specific plug-in without looping through everything.  In order to determine this, there's a couple different ways to handling this.  In this post, we're going to explore a non-MEF way of handling it using LINQ.  In a future post, we'll look at how we can expand upon this using some of the constructs that MEF provides.

Giving Our Messages a New Property

One of the nice thing about using ImportMany(), is that it tells MEF to add the various parts into a collection of type IEnumerable.  What's great about that is that any collection that is derived from IEnumerable is query-able using LINQ.  Because of this, we can use LINQ to select individual or subsets of imported parts.

In this example, we need to modify our IMessage interface to supply it a Name property.  We'll use this property as a label of our decorated part class and then query against it.  Because we're updating the definition of IMessage, we also need to implement the Name property in our SimpleMessage and SecondMessage classes.  We'll set the new properties of our classes to "Simple" and "Second" respectively as well.  Below is the code for SecondMessage at this point for illustration.

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample3
   4:  {
   5:      [Export(typeof(IMessage))]
   6:      public class SecondMessage : IMessage
   7:      {
   8:          public string MyMessage
   9:          {
  10:              get { return "Hello, From a Second Class"; }
  11:          }
  12:   
  13:          public string Name
  14:          {
  15:              get { return "Second"; }
  16:          }
  17:      }
  18:  }

LINQ to ImportMany

Now that we have a property that can be easily identified, let's update our Program class to just output SimpleMessage.MyMessage instead of both.  To do this using LINQ we first need to add the System.Linq namespace.  Next next add a Where() clause to our IEnumerable<IMessage> collection to query against the IMessage.Name property.  Finally, let's output the appropriate message.  Below is what our Program class looks like after all of these changes:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.ComponentModel.Composition;
   4:  using System.ComponentModel.Composition.Hosting;
   5:  using System.Linq;
   6:  using System.Reflection;
   7:   
   8:  namespace MEFExample3
   9:  {
  10:      public class Program
  11:      {
  12:          [ImportMany(typeof(IMessage))]
  13:          IEnumerable<IMessage> Messages { get; set; }
  14:   
  15:          static void Main(string[] args)
  16:          {
  17:              Program p = new Program();
  18:              p.Run();
  19:          }
  20:   
  21:          void Run()
  22:          {
  23:              Compose();
  24:   
  25:              IMessage message = (Messages.Where(m => m.Name == "Simple")).FirstOrDefault();
  26:              Console.WriteLine(message.MyMessage);
  27:              Console.ReadKey();
  28:          }
  29:   
  30:          private void Compose()
  31:          {
  32:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  33:              var container = new CompositionContainer(catalog);
  34:              container.ComposeParts(this);
  35:          }
  36:      }
  37:  }

In this post, we took our collection of imported types and filtered them using LINQ.  MEF provides additional ways to manage this using declarative Metadata attributes which we'll explore in a future post; however, for now, this method should provide a solution during this learning experience.  In the next post, we'll look at expanding our horizons by breakout our imported types into a separate assembly and using different types of part catalogs to achieve such.

Resources


kick it on DotNetKicks.comShout it

Friday, November 13, 2009

A Deeper Look at MEF's Imports and Exports

In the last article, I provided a very brief introduction to MEF and showed a very simple console application.  In this section, we'll be looking at the issues associated with that sample and diving into the various aspects of declaring your Imports and Exports to overcome those issues.  The code and samples in this post will still be within a single assembly.  Because of this, I'll may use the word Dependencies and Parts interchangeably.

The Issues with the Last Example's Simplicity

At the end of the last post, we looked at a simple console application that used MEF to wire our dependencies within the same assembly together.  Below is the code for our Program.cs and SimpleMessage.cs classes again.

Program.cs

   1:  using System;
   2:  using System.ComponentModel.Composition;
   3:  using System.ComponentModel.Composition.Hosting;
   4:  using System.Reflection;
   5:   
   6:  namespace MEFExample2
   7:  {
   8:      class Program
   9:      {
  10:          [Import()]
  11:          string Message { get; set; }
  12:   
  13:          static void Main(string[] args)
  14:          {
  15:              Program p = new Program();
  16:              p.Run();
  17:          }
  18:   
  19:          void Run()
  20:          {
  21:              Compose();
  22:              Console.WriteLine(Message);
  23:              Console.ReadKey();
  24:          }
  25:   
  26:          private void Compose()
  27:          {
  28:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  29:              var container = new CompositionContainer(catalog);
  30:              container.ComposeParts(this);
  31:          }
  32:      }
  33:  }

SimpleMessage.cs

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample2
   4:  {
   5:      class SimpleMessage        
   6:      {
   7:          [Export()]
   8:          string MyMessage
   9:          {
  10:              get { return "Hello, Extensible World"; }
  11:          }
  12:      }
  13:  }

Now, what happens when we change our SimpleMessage class to include a new string property, we'll call it NewMessage, that's also decorated with the [Exprot()] attribute and run the application again?

   1:  [Export()]
   2:  string NewMessage
   3:  {
   4:      get { return "This is another Message."; }
   5:  }

Example2-ChangeRejectedException

Doh! Runtime Error of Type ChangeRejectedException. At this point MEF doesn't know how to wire up our dependencies properly so we'll need to help it out.  First, let's look at what the purpose of Imports and Exports are and how we can use them better.

Defining the Extensibility Contract Using Text Descriptions.

When MEF is composing the various parts of our application together, it attempts to match the members we declare as Exports to matching Imports.  In our initial example, there was only a single Export and Import that were of a matching type (string) and the mapping was easy.  Once we added the second property of the same type, MEF didn't know what to do and attempted to apply both string Exports to our only string Import.  What if we only wanted the SimpleMessage.MyMessage property to be mapped to Program.Message property?  In order to to this, MEF provides options for the Import and Export attributes that allow us to declare a specific label and/or type that can be used in the mapping process.

In order to use a label to declare the mapping, all we would have to do is change the Program.Message  and SimpleMessage.MyMessage declarations to the following:

   1:  public class Program
   2:  {
   3:      [Import("ExampleMessage")]
   4:      string Message { get; set; }
   5:   
   6:      ...
   7:  }
 
   1:  public class SimpleMessage        
   2:  {
   3:      [Export("ExampleMessage")]
   4:      public string MyMessage
   5:      {
   6:          get { return "Hello, Extensible World"; }
   7:      }
   8:   
   9:      ...
  10:  }

As you can see, we provided a simple text description/label to the Import and Export attributes that allow us better control of the mapping.  By making just this update, we can now compile and run the code successfully.

Defining the Extensibility Contract Using Types

For simple cases like this, just passing a text description or label is more than enough to handle the mappings.  But I also said that we could use Types in addition (or in place of) the descriptions to handle the mappings.  In the original example from the last post, we inferred this aspect since the properties were the same type (both were string); however, we can modify our code so that Program.Message took an object instead of just a string.

To implement this change, let's make some changes to our application.  First, let's define a new Interface called IMessage that defines the property MyMessage and have our SimpleMessage class implement it.  Next, we need to make some changes to our Export() declaration.  Since we are now passing types we will want to move the Export() decoration to be class level instead of on the SimpleMessage.MyMessage property and also explicitly declare the Export to be of our IMessage type as shown below.

   1:  [Export(typeof(IMessage))]
   2:  public class SimpleMessage : IMessage      
   3:  {
   4:      public string MyMessage
   5:      {
   6:          get { return "Hello, Extensible World"; }
   7:      }
   8:   
   9:      ...
  10:  }

Lastly, we need to update the code in our Program class by changing three things.  We need to change the Message property to be of type IMessage instead of string.  We should also change the Import() decoration on our property to explicitly expect the IMessage type. And finally, we need to change our output to Message.MyMessage due to the type change.  The updated Program.cs code is shown below.

   1:  using System;
   2:  using System.ComponentModel.Composition;
   3:  using System.ComponentModel.Composition.Hosting;
   4:  using System.Reflection;
   5:   
   6:  namespace MEFExample2
   7:  {
   8:      public class Program
   9:      {
  10:          [Import(typeof(IMessage))]
  11:          IMessage Message { get; set; }
  12:   
  13:          static void Main(string[] args)
  14:          {
  15:              Program p = new Program();
  16:              p.Run();
  17:          }
  18:   
  19:          void Run()
  20:          {
  21:              Compose();
  22:              Console.WriteLine(Message.MyMessage);
  23:              Console.ReadKey();
  24:          }
  25:   
  26:          private void Compose()
  27:          {
  28:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  29:              var container = new CompositionContainer(catalog);
  30:              container.ComposeParts(this);
  31:          }
  32:      }
  33:  }

Now when we run the application, the mappings are still correct and we now have a type specific mapping based on an interface.  In addition to explicitly declaring the type of the mapping, we can also add a label to removing any additional ambiguity if we have multiple classes that implement our IMessage interface but only want to import a specific one.  Though, what if we DID want to import more than one instance of classes that implement our IMessage interface?  Thankfully, MEF has a way for that as well.

Adding a Second Message with ImportMany()

If you can remember the beginning of this specific post, we took our SimpleMessage class and added a second string property which caused our mappings to break since MEF didn't know which string property to map to our then, Program.Message string property. With this situation we addressed it through the use of explicitly declaring the mapping through labels and type abstractions; however, there is another way.  Building on the updates from the last section, what if we were to create a new class that implements our IMessage interface and decorates itself with the Export() attribute?  Let's add a new class to our project called SecondMessage.cs and implement that scenario.  Below is the SecondMessage.cs code:

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample2
   4:  {
   5:      [Export(typeof(IMessage))]
   6:      public class SecondMessage : IMessage
   7:      {
   8:          public string MyMessage
   9:          {
  10:              get { return "Hello, From a Second Class"; }
  11:          }
  12:      }
  13:  }

When we attempt to run the application, we get the same ChangeRejectedExcemption that we did when we had 2 string exports before.  Instead of doing all of the explicit stuff we did previously, let's change our expectations of the number of objects we're importing into our Program.Message property.  MEF addresses this issue by providing an ImportMany() attribute. ImportMany() allows MEF to map many different objects that conform to the contract (label and/or type) to a single property, where as Import() is only a singular mapping.  Since we are now working with multiple instances of IMessage though, we need to update our property to be a collection, as well as update our output to loop through the results.  After applying these updates, Program.cs should resemble the below code.

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.ComponentModel.Composition;
   4:  using System.ComponentModel.Composition.Hosting;
   5:  using System.Reflection;
   6:   
   7:  namespace MEFExample2
   8:  {
   9:      public class Program
  10:      {
  11:          [ImportMany(typeof(IMessage))]
  12:          IEnumerable<IMessage> Messages { get; set; }
  13:   
  14:          static void Main(string[] args)
  15:          {
  16:              Program p = new Program();
  17:              p.Run();
  18:          }
  19:   
  20:          void Run()
  21:          {
  22:              Compose();
  23:   
  24:              foreach(IMessage message in Messages)
  25:              {
  26:                  Console.WriteLine(message.MyMessage);
  27:              }
  28:   
  29:              Console.ReadKey();
  30:          }
  31:   
  32:          private void Compose()
  33:          {
  34:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  35:              var container = new CompositionContainer(catalog);
  36:              container.ComposeParts(this);
  37:          }
  38:      }
  39:  }

Running our application after these latest updates, we see that we get both messages as we expected.  In the next post, we'll take a quick look at how we can manage this need for looping by using LINQ; however, for now,we can see how to we're able to better manage our mappings using Imports and Exports of types and/or labels as well as working with multiple imports.

Resources


kick it on DotNetKicks.comShout it

Thursday, November 12, 2009

Working with the Managed Extensibility Framework (TOC)

This post is simply a table of contents for posts that I'm creating to help others learn about the Managed Extensibility Framework (MEF).  As new posts get published, I'll be updating the links to this page.  In addition, as I work more with MEF, I'll be adding more entries to this series to hopefully cover a wide range of scenarios while using such.

  1. An Introduction to MEF
  2. A Deeper Look at MEF's Imports and Exports
  3. LINQing to MEF Imports
  4. Playing Nice with Other Assemblies using MEF Catalogs
  5. Looking Around at Circular References in MEF
  6. Managing Composition Through Lazy Loading Parts
  7. Using MEF and Custom Configuration Sections
  8. Writing a Custom MEF Part Catalog
  9. Using MEF in F#
  10. More to Come

An Introduction to MEF

Have you ever attempted to write an extensible application?  You know the kind. The applications where your boss wants to be able to add stuff to it without rewriting the entire application and with minimum costs.  Or the type of application you want to release out to the community and provide a way for them to add their own customizations to it.  We have all seen these types of applications; however, if you have ever attempted to write such, it is usually a pain to developer the core application or a pain to develop the extensions or plug-ins.  Thankfully the Managed Extensibility Framework (MEF) is available to those of us that have extensibility needs inside of the application.

Origins and Model

MEF was developed from an initiative within Microsoft in order to simply the creation of building extensible applications.  Developed by Glenn Block and others, the team developed a framework that handled the discovery and composition of the plug-ins/parts to make application extensibility easy to pickup and utilize.  In MEF, a model was developed where decorated parts, containing the extensions of the application, are discovered through catalogs and then composed within a composition container.  What is nice about this model is that it allows for composition at many levels so parts or extensions can include the ability to be extended in addition to extending an application itself (i.e. plug-ins for plug-ins).

How Does MEF Differ From IoC Containers?

During an interview on Hanselminutes episode 148 (Jan 28th, 2009), Scott Hanselman asks Glenn Block how MEF differs from IoC containers.  Glenn provided a very clear (to me) definition of the difference by saying...

You use MEF to manage a set of unknown things. You use IoC containers to manage a set of known things.

Looking at the quote, Glenn makes a good point in that when developers use an IoC container, they typically know of the various types and dependencies they are wiring up through an IoC container.  Sometimes this is configuration based to address differences between environments or just dependencies inside of the code in general. However, when you look at building an application that will allow 3rd party extensions, there's no way of knowing what will be added on.  Now MEF can act like an IoC container but to truly think of it in only that light really places mental limitations on what it can accomplish.

Writing the Hello World

When I started learning MEF, changes had been done since a number of the examples available online were created.  Since we're just getting familiar with MEF in this post, below is a very simple example where MEF is used similarly to an IoC container within a console application.  We'll take this example and greatly expand on it in the next couple of posts; however, for now, I want to just demonstrate the absolute basics to MEF. Before we dive into the code, we need to download the MEF assembly so that we can reference it in our application.

To get the necessary components for integrating MEF into our application, we need to head out to the MEF Project out at Codeplex and click on the Downloads section.  In this series, we'll be focused on MEF Preview (Beta 2) which is compatible with .Net v3.5. In the Downloads section, there should be a link for MEF_Beta_2.zip.  Download and unzip this file.  In the bin directory, you'll want to copy the System.ComponentModel.Composition.dll file.  This is the assembly used to harness the power of MEF.

Now that we have the assembly downloaded, we can create a new console application and reference it. In this demonstration, our simple console application will just output a message.  Very simple, very impractical really but we'll add more practicality over the next posts.  Our console application will need 2 classes; Program.cs and SimpleMessage.cs (shown below)

Program.cs

   1:  using System;
   2:  using System.ComponentModel.Composition;
   3:  using System.ComponentModel.Composition.Hosting;
   4:  using System.Reflection;
   5:   
   6:  namespace MEFExample1
   7:  {
   8:      class Program
   9:      {
  10:          [Import()]
  11:          string Message { get; set; }
  12:   
  13:          static void Main(string[] args)
  14:          {
  15:              Program p = new Program();
  16:              p.Run();
  17:          }
  18:   
  19:          void Run()
  20:          {
  21:              Compose();
  22:              Console.WriteLine(Message);
  23:              Console.ReadKey();
  24:          }
  25:   
  26:          private void Compose()
  27:          {
  28:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  29:              var container = new CompositionContainer(catalog);
  30:              container.ComposeParts(this);
  31:          }
  32:      }
  33:  }

SimpleMessage.cs

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample1
   4:  {
   5:      class SimpleMessage        
   6:      {
   7:          [Export()]
   8:          string MyMessage
   9:          {
  10:              get { return "Hello, Extensible World"; }
  11:          }
  12:      }
  13:  }
There's 3 things here we need to look at.  The Program class contains a string property called Message which is decorated with the [Import()] attribute.  This attribute tells MEF that it is an entry point for extensibility.  The 2nd thing to take note of is that our SimpleMessage class contains a string property called MyMessage and returns the message we want to output to the console window.  This property is decorated with the [Export()] attribute which informs MEF that it can be mapped to an [Import()] member of another type.  Lastly, there are the following 3 lines in our Program class's Compose() method...
   1:  var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
   2:  var container = new CompositionContainer(catalog);
   3:  container.ComposeParts(this);

These 3 lines are used by MEF to discover what parts are available in the current assembly to be imported and compose the parts into the appropriate instance that is extensible (in this case our instance of the Program class).  When we run the project, we see that our message is displayed in the console window without manually mapping SimpleMessage.MyMessage to Program.Message.


This is just a very quick and simple taste of what MEF can do.  In the following posts, we'll dive deeper into declaring Imports and Exports to ensure there not any conflicts during the mapping process as well as demonstrate some options we have on looking for parts outside of our current assembly by using different catalogs.  Until then, please feel free to check out the source code and links located at the bottom of this article for more information on MEF.

Other Resources


kick it on DotNetKicks.comShout it

Tuesday, November 10, 2009

Iowa Code Camp: Session Overview

The Iowa Code Camp was held on  November 7th, 2009 in Des Moines, IA.  With a capacity crowd and a lot of great sessions, it ended up being an awesome time with a lot of great presentations and conversations.  Like conference of this type, you never have time to hit all of the sessions you may want to; however, the ones I was able to attend were still awesome.  Below is an overview on each one.

Getting Started With Behavior Driven Development by Lee Brandt

In his presentation, Lee provided a good introduction to the concepts of BDD.  The presentation focused on the origin of BDD, where it fits, and how it's an evolution of TDD from the beginning which helped to truly set the stage.  For those that have done TDD for a bit, it provided a great introduction into bridging the gap between the business case and the code by using tests as a spec.  Through this and Lee's stressing of an Ubiquitous Language as described in various DDD circles, he showed how BDD can be used in order to provide a technique that helps to show the client what the application will do once done as well as a pseudo-burndown chart of what hasn't been finished yet.  I'm definitely looking forward to exploring BDD again in the near future.

Twitter: @LeeBrandt
Blog: http://www.geekswithblogs.net/leesblog/Default.aspx 

Going From 0 to 100 Dollars an Hour with .Net you Didn't Know by Mitchel Sellers

This session was a good session; however, it wasn't as advanced as I was hoping for.  The abstract of the session focused around using advanced features of .net in order to make you more productive; however, I was hoping for some additional tidbits beyond that of the abstract.  The primary items focused on this presentation were new tips and tricks introduced by .Net 3.5 such as Lambdas, Self Containing Properties, and LINQ. All of these items I already knew and have used them in the past which is why I was hoping for a few tidbits beyond such. That being said though it WAS a good session with a lot of good code samples to convey each concept and technology.  I still learned at least one new thing and was reminded about a few other things as well. While it didn't meet my (probably unrealistic) hopes, I cannot deny that Mitchel's presentation definitely educated a number of people who were also in his session that was overfilled.

Twitter: @MitchelSellers
Blog: http://www.MitchelSellers.com 

Open Spaces

I've been to a few open spaces discussion and have came to the conclusion that some will be good, some will be bad, and others will be between or outside of those labels.  The open spaces session at the Iowa Code Camp was an in between session.  The size of the group was smaller and comprised of a diverse set of primary skills which isn't always a bad thing though the topics in discussion didn't flow like I have experienced in other places.  We had a good conversation about how to get the information to the people that don't come to conferences or how to encourage them to come.  We also talked a little bit about MEF, coding war stories, and some of the side effects of completely rewriting/redesigning an externally facing website.  Lastly we talked a little bit about Kanban vs Scrum and the paradox of software estimation.  All in all there was some good things that came up during the conversation; however, part of me was hoping that more people would have been involved in the discussion and the topics would have been more discussion/problem solving based to an extent.

Intro to ASP.Net MVC by Chris Sutton

I've dabbled in ASP.Net MVC and have wanted to learn more about it; however, finding making the time for such is not always easy.  Everything that I've learned about such has either been about the MVC pattern itself, or about other frameworks in general like Rails or Django.  With only a few MVC Videos watched and about 3hrs worth of coding so far, I decided checking out another intro session wouldn't be a bad idea for me.  Chris Sutton did a great job with the presentation.  He explained the MVC pattern very well as well as describing how the ASP.Net MVC framework relates to it and ASP.Net in general.  He showed a couple of the typical demos for this level of session and afterwards answered all of the questions I had about the next step.  All in all it was a very good session and can't wait until I can make time for using such.

Twitter: @ChrisSutton
Blog: http://subjunctive.wordpress.com 

Silverlight for WPF Developers by Kirstin Juhl

In my opinion, none of the last block of sessions really looked appealing to me.  It wasn't the fact that I didn't think any were going to be good, it was just that I wasn't interested in the topics at hand.  I ultimately decided to check out Kirstin's presentation on what WPF Developers would need to know to transition into the Silverlight space.  While I have only dabbled in WPF a little bit, I knew a number of differences and knew the power of XAML was greater in WPF than Silverlight.  The decision to go here was my current adventures in Silverlight and see what I may be able to learn.  All in all, the session was pretty good for the purpose Kirstin was targeting.  She did a good job at explaining the differences as well as provide information on how to share components between Silverlight and WPF applications (something I knew was possible but hadn't seen an example of up to this point).  Good presentation overall.

Twitter: @KirstinJ
Blog: http://www.geekswithblogs.net/Kirstinj/Default.aspx 

Overall:

Overall, I had a great time at the Iowa Code Camp.  For being a free conference, the presentations, facilities, and of course the prizes were all top notch.  It was a great conference with some amazingly talented speakers and attendees.  All in all I can't wait to head to the next one in the April/May/June timeframe.  Hopefully some of the presentations I'm working on will be ready by then since I'd love to present one.

Friday, November 6, 2009

Reviewing This Year's Goals (2009)

Back in January, I created this post focusing around what I was hoping to accomplish this year.  I was going through my old posts and stumbled across it.  I figured it would be a good time to look over them once again to gauge my progress along with what else I may have done so far this year.

 

Learn F#:

While I do not claim to be an authority of F# by any means, I do feel comfortable in saying that I learned the bulk of the language and be able to determine where it makes sense to use it.  If time allows, I can see myself using it more and more; however, for right now, I've definitely learned a lot from such and can focus on learning other things.

 

Learn DDD:

This one I am really only about 1/2 done with.  While I have went through the information and can understand the concepts involved, I haven't had a good way of applying such yet.  There's existing applications that could benefit from the practices of DDD; but I haven't pushed myself into applying such on a new project yet.

 

Learn Silverlight 2:

I got sidetracked and ended up procrastinated on this one.  While I wanted to learn SL2, I still was a bit apathetic towards it since SL1 wasn't very impressive to me.  Thankfully, I've seen a lot of what Silverlight 3 can do and am going all out on learning more about it.  Except some posts on Silverlight 3 soon.

 

Other Things:

So what else have I been up to so far this year?  Looking back I have worked on some open source projects (namely my SchemaSpy Task for NAnt and contributing to .Net Migrations over on codeplex).  I've also focused a lot of time on keeping up to date on .Net 3.5 and other technologies that I wasn't able to fully take advantage of at a previous employer.  Lastly, I've really been focusing on TDD and just writing better code in general.  There's always room for improvements but being able to learn from what's being talked about over the past year is what's important.

 

Things on the Horizon...

Learning MEF:

The Microsoft Extensibility Framework (MEF) provides some great opportunities to make very extensible applications.  With a need to make a project extensible, I'm definitely going to be focusing on understanding MEF more.

 

Learning Silverlight 3:

I'm already in the process of working in Silverlight 3 but I have only started to write applications with such.  Just like a person who has finished their first true ASP.Net application, there's always room for improvements and things that one can learn to make things better.  I'm at that stage where there's a lot more I can learn about and I'm all for it since Silverlight 3 is awesome.

 

More SchemaSpy:

My SchemaSpy post earlier this year is one of my highest trafficked posts as well as one that I refer back to all of the time.  I'm planning on answering a few outstanding questions associated with that post and also see what else I can do with the tool to make things easier for everyone.

 

<Unknown> Things:

I always leave myself open to the unknown and unforeseen opportunities.  While November and December are usually swamped for me, I never know when inspiration will hit me and I learn something new.