For that we will need of course MEF which is stored in System.ComponentModel.Composition assembly, Autofac and Autofac.MEF packages. Having that in place we can manage our MEF exports with use of autofac container as it would be regular components registered by autofac builder. More on that you can read on autofac documentation, but lets see how it works on a simple example.
Let’s assume we have such a simple plugin interfaceAnd for the sake of simplicity we are exporting class defined in the same library
Now in the client code all we need is to have this
In line 2 we create a composable catalog in the same way as when we use MEF composition. Then we need to call RegisterComposablePartCatalog method so the autofac builder will discover all MEF exports in provided catalog. Now we can simply retrieve the instance of Foo by resolving it from the container.
What about the instantiation? Well, by default all MEF exports are defined as singleton so no matter how many time you request the component you always get the same one instance. This also applies when we resolve mef exports with autofac. To change that we need to set the part creation policy on exported types to NonShared
This is equivalent to InstancePerDependency registration from autofac
Another nice integration feature is that with MEF we can export many components that implements one interface. This is especially useful when we implement plugins. We have one common interface that we want every plugin implements in order to provide added functionality. Then with use of MEF we can simply have a collection of plugins composed on a property of some enumerable type as shown below
With use of autofac container this is even simpler. We resolve it like this
to get immediate instances, or like this
to get lazy loaded instances. That is handy, isn’t it?
One thing that we should know is that the autofac component registrations are not automatically registered and available for types exported with MEF. That means that by default you cannot use components registered in autofac and resolve them inside your exported MEF type. I guess the main reason for this is a security, so your internal components are not available for the external assembly for instance. However we can change that by providing an explicit export of components that we want to have imported in mef components. Let say our Foo class requires some Boo object which is registered with autofac and must be resolved during instantiation of Foo.
In line number 12 we decorate the non default importing constructor which should be used to resolve component, same way as we would define it for MEF composition. To have that working we need to register type Boo as exported component in autofac like this
That’s it. We have now one container for all internal and external components and one way to resolve them. Additionally we can now benefit from all lifetime management features that are part of autofac.