Introduction

MEF was probably one of the best additions to make its
appearance into the .net framework. It brought about a very simplistic way of
providing loosely coupled architecture to your application, by way of an
attribute driven design. That being said, I can certainly go on about the many
advantages MEF provides, but many people have already written extensively about
all its strengths. Instead I’m going to rather discuss how we can harness the
power of MEF and extend it by way of generics. We all use generics to make our
applications code…well more generic, so the question is why Inversion of
control containers can’t support it as well? Well lucky for us MEF can. But not
directly out of the box though, you have to go about setting up a few things
first to get it to fully support generic exports. Lucky for all the beginners
out there, I’m going to show you how to do this.

Getting Started

Let’s kick things off, firstly those of you who haven’t
used MEF and are thinking about integrating this technology into your
application. Please take a look at the following links below to give you some
clarity on this article that will follow.

Design Overview

Once you’ve caught up to speed. We can get to the good
part and discuss how all this works exactly. MEF supports certain types of
catalogs as you know for example we get the AggregateCatalog, DirectoryCatalog
and finally the AssemblyCatalog. Which we all know is highly useful in part
discovery by adding assemblies anyway you see fit. But it doesn’t help when it
comes to generics. It’s simply because the current catalogs seem a bit lack
luster when it comes to finding generic exports and knowing what to do with
them. That’s where the brilliant developers’ from the MEF Contrib team come
into the picture. They’ve developed a catalog that helps to map generic exports
to their concrete types, so you can later import them at run-time like any
other import. There is one slight problem though on their page on codeplex. And
that is the documentation doesn’t exactly give you the slightest idea how to
set it up in a simple way. Some might find it a bit confusing. If you are
however a diligent researcher or a google wizard you can certainly find the
solution. But this article isn’t directed at solving a problem, which has been
done already. This article is meant to save you time as well as help you set it
all up. Just if you are wondering the Mefcontrib dlls and all the files you
need are supplied in the source code above. A quick note if you do want the
latest copy of the library you can go to http://mefcontrib.codeplex.com/. Let’s begin!

Referencing the References

Above you can see all the necessary dependencies for
generic exports to be used. The referenced assemblies are as follows:
MefContrib.dll , System.Composition.dll
and my custom dll Mef.Extended.Tools.

Using the code

Let’s start with the coding aspect of this guide. The
simple part of it all setting up the Catalog as well as the container for our
generic exports. Firstly in your applications startup add the following
references you added to your project earlier, so that you can have access to
the container, catalog, registry etc.

As I’ve showed above, you start by instantiating a GenericContractRegistry
which takes my own custom class TypeResolver as an argument. The TypeResolver’s
constructor accepts a lambda expression is used to filter all the assemblies
that contain exports in them. The GenericContractRegistry is then passed in as
an argument to an instance of the GenericCatalog. Which you’ll see shortly does
all that magic I was talking about earlier. The container then accepts the
catalog as its argument to then compose all exports that are available to later
be imported. Those of you who are a little lost about my custom type, well
don’t stress they will be discussed in depth shortly.

Applying some Exportation

Now that the container is setup to discover exports. You
now need to supply the exports that are going to be used throughout the life
time of your application. Adding exports is exactly the same as what you’ve
been doing with all your previous MEF implementations. it’s the same as before.
For example

One thing to note at time of writing my implementation
only supports the use of InheritedExportAttribute. The reason for this is it
makes more sense to mark an interface or abstract class with an attribute to be
exported rather than the implemented object, purely because of the fact if you
on a big development team like me, a simple thing like marking a class with an
attribute can easily be forgotten. Note this will also work for generic
abstract classes.

Here’s an example repository that Implements our exported
interface. Note both have to be generic types.

Show Me Some Generic Magic

And there we go it’s all working together in harmony, a
working implementation of a generic Export/Import through mef. This has all
been done with marginal effort and even less code. After all one of mef’s
biggest strengths is its simplicity.

Now let’s examine under the hood what’s driving this
little generic engine.

Under The Hood

There are many facets that contribute to mef resolving
generic types for imports, but to keep with the theme of simplicity. Let me
start by saying that it’s really just one big mapping system that assigns an
interface to its implemented concrete type.

This class is the core to mef being able to support
generics. Think of it as one big generic gps. What it does is map an interface
that has the InheritedExportAttribute applied to it, to a concrete implementation
of that specific type. It searches through the assemblies that the TypeResolver
defines based on particular criteria. And it adds it to a custom collection
called AssemblyList. The AssemblyResolver calls this list to get a particular
mapping from each assembly in the collection and then adds it to the register
so that MEF is aware of a new export in the GenericCatalog. You may have
noticed in the MefContrib documentation they tell you to setup a mapping like what
I have commented out above. The problem with setting up a mapping this way is
it continually violates the open/closed principle. Which stipulates a class may
be open for extension but closed for modification. I see this as continually
modifying a class to support more mappings. So I thought of a more dynamic way
of doing this as I’ve explained above. Mef prides itself on part discovery, for
example its DirectoryCatalog looks for parts in directories. So the question is
why we can’t be just as dynamic for our GenericCatalog. It sometimes seems the
best solution is one that is more dynamic more often than not. That was my
rationale behind that little change. Let’s now turn our attention to retrieving
the assemblies that contain the mappings.

The AssemblyResolver class gets all the assemblies that are
referenced in the current application as well as the current applications
executing assembly. This allows the GenericContractRegistry to do an extensive
mapping of all generic exports across all assemblies involved. The search is
narrowed somewhat by the delegate that defines the search criteria for each
assembly, so only the assemblies that meet that particular criteria are
retrieved.

LINQ Marks the spot

The true marvels of modern c#, where would we be without
linq? It makes querying through reflection an absolute treat. The GetMapping()
method creates a dictionary of class types as keys and interfaces that they
implement as values. This simple query associates all interfaces to their
correct implemenations. Above you can see the AssemblyList collection that
takes care of holding all the applications assemblies in a custom assembly
collection.

That's All Folks

I’m not quite done with you avid developers just yet.
Sometimes complex things can be solved with simple ideas, what we achieved was
a mef container that completely supports generics and conforms to the mef way
of doing things. For those of you who enjoy even more of the Nitti gritty and
want to understand how the GenericCatalog works to allow us to have generic
exports, well then I suggest taking a look at this article: http://mefcontrib.codeplex.com/wikipage?title=Generic%20Catalog&referringTitle=Documentation%20%26%20Features Well it’s been an absolute blast to write
this article, it is always easier when you love what you doing though. Hope you
find something useful out of this article. Please remember to vote and comment
if you don’t like something or a suggestion. At the end of the day criticism
just helps you to better understand your flaws so you can come closer to
perfecting them and making them your strengths.

Comments and Discussions

MEF 2 has support for open generics. In fact here is some working code of mine, oh and one more thing with MEF 2 you no longer need the import/export attributes, that is taken care of by new registration API

Thanks Sacha really appreciate the attached code. Yes I've also been playing around a bit with MEF 2's preview release. This article was more for people using MEF 1 in their current systems that wanted the same support as MEF 2 will provide. I'm glad they've abolished the whole attribute thing though.

Hi Sacha I tried using your example of generics with mef 2 but it doesn't work at all. What version of MEF2 are you using? I cannot get MEF 2 preview 5 to work with generics. How would you get it to work?

I am using MEF 2 Preview 3, which worked fine with the stuff I mentioned in my 1st post. If you want to get that version of MEF you can grab it from my my current projects codeplex site : http://codestash.codeplex.com/SourceControl/changeset/view/cb352b4b9623 Its in the LIB folder there under folder called "MEF2 Preview 3". Or you can grab preview 3 from MEF site : http://mef.codeplex.com/releases/view/79090

That definitely works, as I am using that code every day, the code I posted at start of this forum is what I use. Works just fine. Like I say I have that code working every day