eWorld.UI - Matt Hawley

Ramblings of Matt

MEF + Factories Using an Export Provider

November 29, 2008 10:25 by matthaw

After my last post about MEF + Factories, I was chatting with Glenn Block (PM for MEF) about my approach. One of the first things he mentioned is why I hadn't used an ExportProvider. As you know, ExportProvider's are new in the latest drop, and provide an interception point for resolving an import to an export.

 

Taking a look back at the documentation on ComposablePart, I can see why Glenn mentioned this. In it, it states that a ComposoblePart must adhere to to Import/Export contracts. If you've looked at the prior example, you'll see that I'm explicitly violating that rule as I'm finding interfaces based on a base interface, not by Export! At this point, my mind started churning - mainly because there's not a lot of examples or descriptions of what an ExportProvider actually is - but because I wanted to do things "correctly" according to the framework provided. (As an aside, Glenn stated that a "What is an Export Provider" post or documentation is coming, maybe this'll boost that necessity!) What I ultimately came up with was a much cleaner solution than using a FactoryPartCatalog.

 

Introducing FactoryExportProvider:

   1:  public class FactoryExportProvider<T> : ExportProvider {
   2:     public FactoryExportProvider(Func<Type, T> resolutionMethod) { }
   3:     public FactoryExportProvider(Assembly assembly, Func<Type, T> resolutionMethod) { }
   4:     public FactoryExportProvider(IEnumerable<Type> types, Func<Type, T> resolutionMethod { }
   5:  }

What you'll see is again, it's very straight forward and provides a clean implementation in usage, just as the part catalog example did. Each constructor does just as it had done in the part catalog, so I'll not explain that again. One thing that I discussed with Glenn about was, is it appropriate to look for certain types within an Export Provider? His response was "absolutely you can do that". good, I think I've found the correct implementation, both from less code/object graph standpoint, but also from an intention standpoint.

 

Internally, the code is very simplistic. Since I'm finding these interfaces on-the-fly, and need more information than just the contract name, I needed to use a FactoryExportDefinition to store this information. I've you've looked at the prior example, you'll see this came back out of necessity.

   1:  public class FactoryExportDefinition<T> : ExportDefinition {
   2:     public FactoryExportDefinition(string contractName, Type type, Func<Type, T> resolutionMethod) { }
   3:   
   4:     public override string ContractName { get { ... } }
   5:     public Type ServiceType { get; private set; }
   6:     public Func<Type, T> ResolutionMethod { get; private set; }
   7:  }

When finding all of the interfaces that implement the base interface specified in the FactoryExportProvider, I convert those into a list of FactoryExportDefinition objects. Reason being, is that the export provider compares an ImportDefinition to an ExportDefinition when finding all available exports. This comparison is done by implementing the GetExportsCore method. The idea of export providers, is that when resolving all dependencies, MEF will call into all of the registered ExportProviders to determine if they can supply the Export and will do a bunch of cardinality matching for you. Out of the box, MEF provides an export provider for it's registered part catalogs. Here's the FactoryExportProvider's implementation of GetExportsCore.

   1:  protected override IEnumerable<Export> GetExportsCore(ImportDefinition importDefinition) {
   2:     IList<Export> exports = new List<Export>();
   3:     var constraint = importDefinition.Constraint.Compile();
   4:     var foundExports = from d in definitions
   5:                        where constraint(d)
   6:                        select new Export(d, () => d.ResolutionMethod(d.ServiceType));
   7:   
   8:     if (importDefinition.Cardinality == ImportCardinality.ZeroOrMore)
   9:        exports = foundExports.ToList();
  10:     else if (foundExports.Count() == 1)
  11:        exports.Add(foundExports.First());
  12:   
  13:     return exports;
  14:  }

It's that simple. The Export's that are returned will have the resolution method called when the actual object is needed. When it comes down to including this within your application, it's just as easy as it was for the part catalog, you just register things a bit differently.

   1:  public interface IService { }
   2:  public interface IUserService : IService { }
   3:   
   4:  [Export]
   5:  public class UserController {
   6:     [ImportingConstructor]
   7:     public UserController(IUserService userService) { }
   8:  }
   9:   
  10:  // in your application
  11:  private void Compose() {
  12:     var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());
  13:     var factoryProvider = new FactoryExportProvider<IService>(GetService);
  14:     var container = new CompositionContainer(catalog, factoryProvider);
  15:     container.AddPart(this);
  16:     container.Compose();
  17:  }
  18:   
  19:  public IService GetService(Type type) { return ... }

And that's it. Ultimately, this leads to a cleaner implementation that uses less types that you have to manage, and, adheres to the correct intentions of the framework. Much thanks to Glenn who I chatted with for several hours last night! You can get the downloadable source here. Enjoy!

 

kick it on DotNetKicks.com


Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: .NET | MEF | Programming
Actions: E-mail | Permalink | Comments (13) | Comment RSSRSS comment feed

Comments

November 29. 2008 23:29

Pingback from weblogs.asp.net

MEF + Factories Using an Export Provider - eWorld.UI - Matt Hawley

weblogs.asp.net

November 30. 2008 14:46

Pingback from blogs.msdn.com

My Technobabble : Export Providers and Custom factories with MEF

blogs.msdn.com

November 30. 2008 15:26

Pingback from feeds.feedburner.com

Export Providers and Custom factories with MEF - Glenn Block

feeds.feedburner.com

November 30. 2008 15:43

Pingback from codebetter.com

Export Providers and Custom factories with MEF - Glenn Block

codebetter.com

December 2. 2008 18:15

Pingback from taccato.com

Export Providers and Custom factories with MEF - taccato! trend tracker, cool hunting, new business ideas

taccato.com

April 21. 2009 15:08

very goods another too be me.

saç ekimi

May 20. 2009 06:47

I have been working on MEF for couple on year now and i dint find anything like this before.Thanks a lot

Define

May 20. 2009 06:51

Very nice post.I was looking for it for quite a sometime now

Lennox Furnace Filters

May 21. 2009 00:33

Thanks for the very informative post!It's good somebody takes real interests in these things and shares them.

Bakersfield dating

June 2. 2009 15:19

I n the internet, it really is a wonder how there will always be people to make things easier when things are not that easy yet. Just like this post here.

Thanks for sharing. It was helpful.

Milan Flights

June 4. 2009 00:55

A nice article on Factories using Export Provider. Thanks for this helpful post.

Website Design

June 20. 2009 13:48

Wow nice info you have here. I hope this will help a lot of people. I will tell my friends to read this. Thanks

Allan

June 27. 2009 01:59

Very Informative. One hell of a code you got here. This is worth reading. Thanks!

Star Trampoline

Add comment


 

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

July 3. 2009 21:47



Copyright © 2000 - 2009 , Excentrics World