A Mef CompositionContainer
is unable to resolve Autofac dependencies when used according to documentation at http://docs.autofac.org/en/latest/integration/mef.html.
I have a large code-base that has extensive use of a ServiceLocator and singletons... The service-locator does all object-creation, composition etc by using a cached System.ComponentModel.Composition.Hosting.CompositionContainer
. (Also, note that we currently use/need metadata support) I am attempting to switch from this to a more modern architecture. For this to work, the existing Mef-based (‘CompositionContainer’-based) service-locator will have to cooperate with the Autofac IoC container.
The following function
CompositionContainer
AutofacExport
to MEF by using the .Exported
extension method.The exception thrown is: ImportCardinalityMismatchException("No exports were found that match the constraint: ContractName MefExportWithDependency RequiredTypeIdentity MefExportWithDependency"
is thrown.
public void MefResolve_ObjectWithDependency_CanResolveWhenAutofacRegistersDependeyncy2()
{
//1. Initialize Mef
var composablePartCatalogs = new List<ComposablePartCatalog>
{
new AssemblyCatalog(Assembly.GetExecutingAssembly())
//A lot more here..
};
var aggregateCatalog = new AggregateCatalog(composablePartCatalogs);
var container = new CompositionContainer(aggregateCatalog, true);
//2. As expected this is resolved
container.GetExport<MefExport>().Should().NotBeNull();
//3. Initialize Autofac
var builder = new ContainerBuilder();
builder.Register(c => new AutofacExport()).Exported(x => x.As<AutofacExport>());
builder.RegisterComposablePartCatalog(aggregateCatalog);
var ioc = builder.Build();
//4. Here Autofac is correctly providing the dependency to the mef ImportingConstructor
ioc.Resolve<MefExportWithDependency>().AutofacExport.Should().NotBeNull();
//5. The next line will throw ImportCardinalityMismatchException
container.GetExport<MefExportWithDependency>();
}
There code above expects the following classes to be defined:
public class AutofacExport { }
[Export]
public class MefExport { }
[Export]
public class MefExportWithDependency
{
public AutofacExport AutofacExport { get; set; }
[ImportingConstructor]
public MefExportWithDependency(AutofacExport autofacExport)
{
AutofacExport = autofacExport;
}
}
Note: I have also had a look at https://www.nuget.org/packages/MefContrib.Integration.Autofac/ - which promises to integrate Mef with Autofac. However, I am not able to find relevant documentation on how to configure that, and the package does not have a lot of usage.
I think you may have misunderstood the way the Autofac.Mef package is supposed to work. While it brings MEF items into Autofac, letting Autofac understand the export/import attributes and items registered in the MEF catalogs, it's a one-way operation - it doesn't push Autofac registrations into MEF or allow a MEF CompositionContainer
to use Autofac.
I believe what you want is the MefContrib.Integration.Autofac package you mentioned, which appears to allow things to flow the other direction - from Autofac into MEF.
A good place to see how it works is in their repository, where they have some unit tests showing integration where MEF is resolving Autofac items. Here's one such test:
[Test]
public void ExportProviderResolvesServiceRegisteredByTypeTest()
{
// Setup
var builder = new ContainerBuilder();
builder.RegisterType<AutofacOnlyComponent1>().As<IAutofacOnlyComponent>();
var autofacContainer = builder.Build();
var adapter = new AutofacContainerAdapter(autofacContainer);
var provider = new ContainerExportProvider(adapter);
var component = provider.GetExportedValue<IAutofacOnlyComponent>();
Assert.That(component, Is.Not.Null);
Assert.That(component.GetType(), Is.EqualTo(typeof(AutofacOnlyComponent1)));
}
As you can see, they have an adapter for Autofac containers that sort of "converts" them into something MEF can understand. They also have some unit tests showing bi-directional integration - MEF resolving from Autofac, Autofac resolving from MEF.
I've never personally used that package, but I think if you check out the tests and how they've got those set up it should get you on your way.