MEF integration and constructor injection

315 views
Skip to first unread message

Scott Bussinger

unread,
Oct 10, 2010, 8:55:08 PM10/10/10
to Autofac
I'm running into an error that seems to me should work, but perhaps
it's a limitation in how the MEF integration stuff works. If someone
could tell me if this is supposed to work or not, that'd be very
helpful.

I'm trying to resolve a class from my Autofac container that was added
using using the MEF integration stuff
"Builder.RegisterComposablePartCatalog(new DirectoryCatalog(...))".
The problem seems come from a parameter in the constructor that I'd
like resolved.

The class is declared something like this:

[Export]
public class MyClass
{
[ImportingConstructor]
public MyClass(Logger logger) {}
}

When I try to resolve MyClass I get an exception in
Autofac.Integration.Mef.RegistrationExtensions.cs:

ComponentNotRegisteredException was unhandled by user code
The requested service 'ContractName=NLog.Logger' has not been
registered.

I can resolve Logger in classes that are not being registered by the
MEF stuff so I know it's registered. I've tried other class types as
well and get the same sort of error. It complains if I don't have the
"[ImportingConstructor]". If I remove the constructor parameter it
works.

So my question is, should this work?

Thanks!

Scott Bussinger

unread,
Oct 11, 2010, 4:49:47 PM10/11/10
to Autofac
I did a bit of debugging and I'm thinking that way things work is that
in order to resolve a MEF registered type, all of it's constructor
dependencies must also be MEF registered.

In Autofac.Integration.Mef.RegistrationExtensions we've got

static IEnumerable<IComponentRegistration> ComponentsForContract(
this IComponentContext context,
ContractBasedImportDefinition cbid)

While debugging I see that cbid.Constraint is

{exportDefinition => ((exportDefinition.ContractName ==
"NLog.Logger")
AndAlso
(exportDefinition.Metadata.ContainsKey("ExportTypeIdentity")
AndAlso
"NLog.Logger".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))}

I won't pretend that I understand what's going on so deep inside
Autofac, but I'm assuming those "AndAlso" clauses are requiring the
NLog.Logger to be a MEF exported type. Is that correct? As an
experiment, I tried explicitly registering the type in Autofac with an
Export() clause and sure enough it worked.

Any reason for this restriction? Are MEF registered types actually
instantiated by MEF in these cases and not Autofac?

Scott Bussinger

unread,
Oct 11, 2010, 4:54:07 PM10/11/10
to Autofac
The reason this is tough for me is that the NLog.Logger isn't being
registered in a normal way and is actually being created through a
module like this:

public class AutofacLoggingModule : Module
{
protected override void
AttachToComponentRegistration(IComponentRegistry registry,
IComponentRegistration registration)
{
registration.Preparing += OnComponentPreparing;
}

static void OnComponentPreparing(object sender,
PreparingEventArgs e)
{
var t = e.Component.Activator.LimitType;
e.Parameters = e.Parameters.Union(new[] { new
ResolvedParameter((p, i) => p.ParameterType == typeof(Logger), (p, i)
=> LogManager.GetLogger(t.FullName)) });
}
}

It's not clear how I'd Export this for MEF. Any thoughts on how I'd
get it registered as an Export?

Nicholas Blumhardt

unread,
Oct 12, 2010, 11:57:28 PM10/12/10
to aut...@googlegroups.com
Hi Scott,

I don't believe this scenario can be supported in the MEF integration. The integration does not extend MEF with any of Autofac's capabilities like the example you've given below. You may need to register a default ILog implementation for all MEF components to consume.

Hope this helps.

Nick


--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To post to this group, send email to aut...@googlegroups.com.
To unsubscribe from this group, send email to autofac+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/autofac?hl=en.


Scott Bussinger

unread,
Oct 17, 2010, 4:56:27 AM10/17/10
to Autofac
> I don't believe this scenario can be supported in the MEF integration.

Thanks for letting me know Nick.

It's not quite as clean, but I worked around it by not using the MEF
integration that comes with Autofac. Instead I used MEF the "normal"
way to load in the assemblies. I added the concrete Type of the
exports to their own metadata so I could register the classes MEF
composed into the Autofac container. I could then resolve them using
the full features of Autofac after dynamically loading them with MEF.

Reading back through that, I'm not sure it'll make sense to anyone be
me, but it works and that's what counts. :)
Reply all
Reply to author
Forward
0 new messages