Posted on 12/1/2008 10:16:35 PM by Justin Etheredge
In the last part of this series on the Managed Extensibility Framework, I showed you how MEF can let you set classes as exports, then declare a property as an import, and MEF will "plug-in" these types to the property. What we ended up with was two different types which wrote out to the console in different colors. In order to do this, we used an "AttributedAssemblyPartCatalog" which is just a part catalog that takes an assembly reference in order to discover all types which have "ExportAttribute" applied to it:
private void Compose()
{
var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.AddPart(this);
container.Compose();
}
In this post we are going to check out a different type of part catalog that instead of taking an assembly reference it takes a folder:
var catalog = new DirectoryPartCatalog(@".\plugins", true);
This is great because this allows us to have a folder in our application where we can just drop assemblies into and this part catalog will grab all of them and add them each as "AttributedAssemblyPartCatalog"s which will, as we said earlier, import all types that have "ExportAttribute" applied to them.
In this example we are going still use the IConsoleWriter interface from the last post, and we are going to put console writers in multiple dlls:
Inside of our console app's directory we are going to create a plugins folder. We will be able to place dlls in this folder and MEF will retrieve exports from these dlls automatically. First I am going to create a host class to run all of our code from:
[Export(typeof(ConsoleWriterHost))]
public class ConsoleWriterHost
{
[Import]
public IEnumerable<IConsoleWriter> ConsoleWriters { get; set; }
public void Run()
{
foreach (IConsoleWriter consoleWriter in ConsoleWriters)
{
consoleWriter.Write("Hello from the console!");
}
}
}
Now that we have this host which imports our "IConsoleWriter"s and exports itself, we can fire up our application like this:
public static void Main(string[] args)
{
var catalogs = new ComposablePartCatalog[]
{
new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly()),
new DirectoryPartCatalog(@".\plugins", true)
};
var catalog = new AggregatingComposablePartCatalog(catalogs);
var container = new CompositionContainer(catalog);
container.Compose();
var consoleWriterHost = container.GetExportedObject<ConsoleWriterHost>();
consoleWriterHost.Run();
}
In this code we are declaring two part catalogs in an array. One is an "AttributedAssemblyPartCatalog" which will allow us to gather up the Exports from the current dll (which is the ConsoleWriterHost) and then second is a "DirectoryPartCatalog" which points at the "plugins" folder and gets our exports.
We then pass these catalogs into an "AggregatingComposablePartCatalog" which is a catalog that simply takes in multiple other catalogs. We then pass it into the "CompositionCatalog" and call "Compose" just as we always do. After that we call the "GetExportedObject" method on the container to request the ConsoleWriterHost and then run it. Depending on what dlls we have in the plugins directory, we will get a different number of "IConsoleWriter"s. If we have these dlls in the folder:
Then we will get this output:
Now that you have seen how to get exports from external dlls, I hope you can start to see a little bit of the cool features that MEF has to offer you. In the next entry we are going to look at export lifetimes and see how we can have our imports get updated whenever we drop new dlls in the folder.