Friday, December 16, 2011

Writing an Extensible Application – Part 4: MEF

 

Hi All,

This is the 4th and final part of the extensibility series and this time I will talk about MEF (Managed Extensibility Framework). MEF was an open source project on codeplex but in .Net framework 4 (and SL 4) it was included within the framework itself. MEF is a very simple way to allow extensibility in your application.

A short reminder: We have an application consisting of two projects, the main application and the interfaces Dll which we ship to our clients. The client references the interfaces Dll and implements the required interfaces. This time the extensibility project is called Extensibility and it uses MEF to extend our application. To use MEF in .Net 4 project you simply have to reference System.ComponentModel.Composition (from the framework). Now things couldn’t be simpler. All you need to do is to mark your implemented classes with the Export attribute which will allow the MEF mechanism to identify these implementations as your extensibility implementations. You can pass a type to this attribute stating under which type the implemented class will be imported.

So the code didn’t change too much except these things:

  1. [InheritedExport(typeof(ICollider))]
  2. public class BasicCollider : ICollider
  1. [InheritedExport(typeof(IDrawer))]
  2. public class BasicDrawer : IDrawer
  1. [InheritedExport(typeof(IMover))]
  2. public class BasicMover : IMover

and in the main application the loading is much simpler now:

  1. private void LoadExtensibility()
  2. {
  3.   Assembly applicationAssembly =  Assembly.GetAssembly(GetType());
  4.   string extensibilityPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(applicationAssembly.Location), ConfigurationManager.AppSettings["Extensibility"]);
  5.  
  6.   AggregateCatalog catalog = new AggregateCatalog();
  7.   catalog.Catalogs.Add(new DirectoryCatalog(extensibilityPath));
  8.   _container = new CompositionContainer(catalog);
  9.  
  10.   try
  11.   {
  12.     this._container.ComposeParts(this);
  13.   }
  14.   catch (CompositionException compositionException)
  15.   {
  16.     Console.WriteLine(compositionException.ToString());
  17.   }
  18.  
  19.   IEnumerable<Lazy<ICollider>> tempColliders = _container.GetExports<ICollider>();
  20.   foreach (Lazy<ICollider> collider in tempColliders)
  21.     Colliders.Add(new StrategyAdapter(collider.Value));
  22.  
  23.   IEnumerable<Lazy<IMover>> tempMovers = _container.GetExports<IMover>();
  24.   foreach (Lazy<IMover> mover in tempMovers)
  25.     Movers.Add(new StrategyAdapter(mover.Value));
  26.  
  27.   IEnumerable<Lazy<IDrawer>> tempDrawers = _container.GetExports<IDrawer>();
  28.   foreach (Lazy<IDrawer> drawer in tempDrawers)
  29.     Drawers.Add(new StrategyAdapter(drawer.Value));
  30.  
  31. }

I won’t go into details about the use of MEF but basically I linked the extensibility folder “Extensibility” with the composition container which magically read the dlls from that folder and added the exported classes so that I can later read them using the GetExports method.

Summary

I have presented 3 ways of making your application extensible. The first involved reflection only and wasn’t a real extensibility framework but merely a poor man’s solution (which sometimes may be enough). The second solution involved an open source framework (IC#Core) which is a bit obsolete and gives only the infrastructure into which you need to add content. The third solution is the MEF framework which gives you some nice options (such as hot swapping) but if you use it without the source code there is too much “automagical” stuff going on there (at least for me). I think the main take-away here is the design of the application. If you followed the example throughout the four parts you have noticed that due to the design of the application the changes I had to make to move from one extensibility framework to the other were quite minor.

 

Thank you for reading,

Boris

No comments:

Post a Comment