Saturday, March 20, 2010

MEF and IoC/DI (3)

Here is the way how MEF interacts with the class. When there is a request to get an instance of IProcessController from MEF, MEF will create an instance of DIResolver since MEF knows the Export is defined in this DIResolver class. At the time when the instance is created, the two Import properties are injected with instances of IDataReader and ILog. Finally, the property getter marked as the Export type of IProcessController type is called with the result instance from MEF and then to the request.

You could place many or all Imports and Exports in one DIResolver class, but I prefer to define DIXXXResolver in a logical way so that it contains only the related mapping relationships, for example, DIContollerResolver for resolving the export of IProcessController, DIDataReaderResolver for the export of IDataReader, and DILogResolver for the export of ILog.

OK. I think is very clear about the concept of Export and Import as Parts in MEF in terms of DI. How are the parts (Import and Export) loaded to MEF so that the expected instances can be retrieved from the framework?

In MEF, all the parts are loaded to a DI container, which is called as CompositionContainer class. The container class interacts with Parts actually through another layer called as Cataglog. This is a very interesting and powerful structure. MEF currently supports four types of Catalog classes and they all inherited from ComposablePartCatalog class:

Those catalogs are straightforward by their names. For example, AssemblyCatalog is used for loading parts within an assembly; DirectoryCatalog for loading parts by specifying a folder or file pattern; TypeCatalog for loading a list of specific set of types; and AggregateCataglog for loading a list of catalogs. The first three are most commonly used ones. With this design of structure, Catalog class provides a wild range of strategies to load parts to a MEF container.

For example, I use the AssemblyCatalog to load a list of assemblies or DI libraries where DIXXXResolver classes are defined. I can also put some DI library and related library files in one folder, such as "DIExtensions". Then the folder is loaded by DirectoryCatalog. This makes it possible to dynamically add new extensions or update extensions without rebuilding or compiling my application source codes.

Although it is very easy to load Catalogs to MEF, you still need to understand and follow MEF pattern to do that. As you will find out, MEF contains a wild range of types, classes, interfaces and attributes. It may be very confusing or intimidating for beginners. I'll stop here about further explain MEF; instead, I'll show you three help classes I have created. Those classes provide very simple APIs to define DI mappings, to load DI catalogs, to retrieve instances, as well as other benefits you can get from them.

Still I think it will be very helpful to visit MEF class library and documentations when you see some MEF terms in my classes.