As I have already discussed some of the Catalogs present in MEF library viz, TypeCatalog, AssemblyCatalog etc, where AssemblyCatalog is actually a collection of TypeCatalog internally, DirectoryCatalog on the other hand is a collection of AssemblyCatalog. In this post I will look into DirectoryCatalog and how to use this class while writing your MEF application.
DirectoryCatalog is a Type that maps a Directory in the File system. In general purpose development of Pluggable application, we generally put our plugins in a Directory specific to the application such that when a new dll is put into that directory the application starts working with it. DirectoryCatalog exposes few members from it that enables you to easily map the directory to the container.
Say I have an application that host a number of plugins in it. Say in our simple environment we have defined two class library each of them exporting one method.
public class ExportContainer { public string ExportName { get; set; } [Export] public string GetName() { this.ExportName = "Plugin from Plugin1"; if (this.MyActionDelegate != null) this.MyActionDelegate(this.ExportName); return this.ExportName; } [Export] public Action MyActionDelegate { get; set; } }
The other plugin does the same thing just the string is different. Now when we try to map a directory where the assemblies are put we get its parts defined within it.
Say for instance we define our host like this :
static void Main(string[] args) { DirectoryCatalog catalog = new DirectoryCatalog("plugins", "*.dll"); catalog.Changed += new EventHandler(catalog_Changed); Console.WriteLine(catalog.Parts.Count()); Console.ReadKey(true); Console.WriteLine("Refreshing catalog !"); catalog.Refresh(); Console.WriteLine(catalog.Parts.Count()); Console.ReadKey(true); } static void catalog_Changed(object sender, ComposablePartCatalogChangeEventArgs e) { Console.WriteLine("Directory modified"); }
Here we use Refresh which will recreate the parts again. The DirectoryCatalog implements INotifyComposablePartCatalogChanged and invokes the event whenever a new Assembly is loaded from the directory.
Now to run the project, we create a directory called plugins into the bin\debug folder of the main host. We compile the plugin1 and put it into the directory.
Now if I run the host application it will create the object of DirectoryCatalog and enumerate all the Parts into it. Currently it has only one assembly, hence it will show 1 in it.
Thus you can see it shows 1 which indicates the count of Parts currently enumerated into the DirectoryCatalog. Now we put the other assembly into the Directory.
After we put the second assembly into the folder we still cannot see the assembly is enumerated into the DirectoryCatalog. It exposes a method called Refresh that does recreate the parts from the assembly for us. Thus if you press enter, it will first invoke the CatalogChanged Event which we handle and finally recreate the whole Directory catalog again.
Hence the final output of the console looks like :
The line Directory modified only comes when the Refresh sees that the directory contains assemblies that were not present before. Thus it changes the existing Parts enumeration and also invokes the event.
DirectoryCatalog is used most often in MEF applications.
Remember: You cannot change the Path or Search pattern of the DirectoryCatalog once the object is created.
Download sample code from here.
Read more about it from the links :
Managed Extensibility Framework – A Look
Steps to write a plugin based application with MEF
Thank you for reading.