Nimish David Mathew
Nimish David Mathew

Reputation: 3168

Autofac resolving named service incorrectly

I am using AutoFac for dependency injection and I have the following code in the global.asax file.

builder.RegisterType<GenderMapper>()
    .As<ICodeMapper>().Named<ICodeMapper>(ValueSets.Gender.ToString());

builder.RegisterType<LanguageMapper>()
    .As<ICodeMapper>().Named<ICodeMapper>(ValueSets.Language.ToString());

builder.RegisterType<MaritalStatusMapper>()
    .As<ICodeMapper>().Named<ICodeMapper>(ValueSets.MaritalStatus.ToString());

builder.RegisterType<RelationshipMapper>()
    .As<ICodeMapper>().Named<ICodeMapper>(ValueSets.Relationship.ToString());

builder.Register<Antlr.Runtime.Misc.Func<string, ICodeMapper>>(c =>
{
    var componentContext = c.Resolve<IComponentContext>();
    return (roleName) =>
    {
        var codeMapper = componentContext.ResolveNamed<ICodeMapper>(roleName);
        return codeMapper;
    };
});

Where ValueSets is an enum. I resolve the services like so:

var codeMapper = _codeMapperFactory(mapperInstanceName);

Where _codeMapperFactory implements ICodeMapper and is the base abstract class for the 4 mappers registered above.

The problem is that, whatever be the value of mapperInstanceName be, I am always getting the mapper registered last (ie. RelationshipMapper).

When I debug, the costructor being called is of RelationshipMapper whatever be the value of the argument passed to the factory.

What could be the reason for this?

Upvotes: 3

Views: 274

Answers (1)

Travis Illig
Travis Illig

Reputation: 23934

There's a lot to unpack here and may require some back and forth discussion because there's not really enough info, but I'm a little short on time and would like to get you an answer to help you. I may or may not be able to make it back here so if my answer doesn't work it'd be better if you update your question with additional info rather than comment and sit and wait for me.

So.

I see that you've registered the mappers both as unnamed and named implementations of ICodeMapper. I also see that RelationshipMapper is the last one in, which means if you resolved an unnamed implementation that's the one you'd get.

// You'd get RelationshipMapper
container.Resolve<ICodeMapper>();

I also see that there's an Antlr.Runtime.Misc.Func<string, ICodeMapper> being registered. I don't know what that type is, but I can see high potential for it to conflict with System.Func<string, ICodeMapper>.

Autofac handles System.Func so if that's being called, you'd get an unnamed instance.

// You'd get RelationshipMapper
var f = container.Resolve<Func<ICodeMapper>>();
f();

Here's what I'd check:

  • Make sure you can manually resolve your named mappers, just to ensure that works.
  • Make sure you're resolving the Antlr Func and not System.Func.
  • Try removing the As<ICodeMapper> and only use Named<ICodeMapper> if you're not resolving any unnamed types. You may start getting an exception and that may help you further troubleshoot. Like if Autofac throws an exception about no ICodeMapper being registered, you'll know it's not resolving named things, it's trying to resolve unnamed things.
  • Throw an exception from your Antlr Func instead of calling componentContext.ResolveNamed. See if that ever actually gets hit. (I have bad luck setting breakpoints in those generated functions-from-functions. You could also try a breakpoint in there.)

Hope that helps.

Upvotes: 2

Related Questions