Monday, November 29, 2010

Microsoft Extensibility Framework

I have done a lot with reflection over the years. In the day it was a cool tool but because it was often grammatical a pain in the ... it lost it's way with me. I recently attended VS Live 2010 in Orlando and was reignited into the use of reflection or what we now call MEF (Microsoft Extensibility Framework). Microsoft has done all that clumsy work that used to make Reflection difficult for us.

My real world use is of course with WCF (Windows Communication Foundation). I produce a large number of services that talk to multiple outside partners exchanging product, inventory and order information. I have been working on ways to reduce the number of WCF services and thus TCP/IP ports. Reflection was one way where we could create one service and then dynamically call an interface based library for each timed service call. In other words at timed intervals we we make an interface call to a CRUD method that is exactly the same on every service. That service decides what to do on each of those interface calls.

Here is an example of what the code would like like in reflection:

var asm = Assembly.LoadFrom(Path.Combine(Environment.CurrentDirectory, "service.dll"));
var type = asm.GetType("service.serviceimp");
var service = Activator.CreateInstance(type) as IChannelInterface;
service.Create();


As you can see this has several areas that can cause both performance issues and flat out exceptions.
Anything in quotes makes me look twice, but to put the name of a library in quotes to me is just plain insane. This means first and foremost the very thing I was going for, not being bound to the library is now bound. Second, what if I spell it wrong, we all know how programmers spell, that's why some folks never leave VB. Last it means I can not change the name of the library without affecting some other program (I'm tightly bound again). Exception possibilities are numerous here but through this into a console application and try and run it.

So Microsoft wrapped this all up for us and in conjunction with the new Parallel library I was able to get the following to do the exact same reflection code from above:

var container =
new CompositionContainer(
new DirectoryCatalog(Environment.CurrentDirectory));
container.ComposeParts(this);

var t = Services.AsParallel();

t.ForAll(x => x.Create());


Now this is my kind of coding, nothing to specifically identify a library, multi-threaded and most of all NO QUOTES. So what are we doing here? We are using the CompositionContainer (a new MEF class) to say load everything in the currently executing direction that is marked as exported (we'll get to this in a second), ComposeParts, which means create the attributed parts from the composed container or in English, look through all the libraries for anything attributed for exports and compose those into usable parts so that our application can call the CRUD methods identified in the interface. The following code is placed at the top of the service:


[ImportMany()]
public List Services { get; set; }


This contains a reference to the ImportMany attribute, another member of the MEF framework, identifies a storage place for reflected objects highlighted below. This list of IChannelService objects can be iterated over as a parallel query as seen in the ForAll extension method identified in the code above.

The only way to make all this work is to expose you classes/methods to the MEF framework via an attribute. In this case:

[Export(typeof(IChannelService))]


This exposes the class, inheriting from IChannelService to the MEF framework so that when ComposeParts is called above it know what to expose. This is the glue that bind.

There is much more to discuss including many import features and export features that make a very open framework. Please feel free to post if you have questions.

No comments: