Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to resolve an instance from Autofac, given only a string key?

Tags:

autofac

Using Autofac, is it possible to do this? I don't have the type of the instance.

var instance = container.Resolve("someStringKey");

From some Googling, it doesn't seem to be possible, but I wanted to be sure.

Thanks.

like image 909
ck. Avatar asked Feb 02 '12 17:02

ck.


1 Answers

The short answer is: No, out of the box you have to have the type.

You should have the type because, technically speaking, you can register two different named services with different types:

builder.RegisterInstance(someObject).Named<IFoo>("name-here");
builder.RegisterInstance(someOtherObject).Named<IBar>("name-here");

Without the type, you'll sort of "get what you get," if you know what I mean. It won't be predictable.

There is no officially supported way to get what you're looking for, but you can maybe hack yourself a solution. Something like this:

public static object ResolveUntypedNamed(
  this IComponentContext context,
  string serviceName)
{
  var component = context.ComponentRegistry.Registrations
    .Where(r => r.Services.OfType<KeyedService>()
      .Any(s => s.ServiceKey.Equals(serviceName)))
    .FirstOrDefault();
  return context.ResolveComponent(component, Enumerable.Empty<Parameter>());
}

However, I can't really recommend doing that. One of the things that makes Autofac flexible is the ability to have "registration sources" that can do some interesting late-bound things. When you resolve a service "the right way" there's some initialization and scanning that goes on to make sure everything that needs to be dynamically registered actually gets dynamically registered. When you access the list of registrations on the component registry, it's the list of everything that's registered up to that point, which may not contain the named service you're looking for... in which case you'll fail the resolution when you otherwise might not.

If you're not using any of the dynamic registration stuff in your app, you're probably safe. Just be aware that you are sort of going around-the-side with something like this and you may not get the expected results. If/when weird things start happening, you've been warned.

If you want to register and resolve untyped services "the right way," you probably will need to implement your own Autofac.Core.Service. Keyed/named registrations are Autofac.Core.KeyedService but they always have a type associated; your custom one would need to not be typed. You'd then need to implement your own registration extensions on the ContainerBuilder such that you can do something like:

builder.RegisterUntypedNamed(someObject, "name-here");

...and then you'd also need a corresponding extension on IComponentContext to resolve your service type so you could correctly do:

container.ResolveUntypedNamed("name-here");

...while still participating in all of the late-bound registration/scanning stuff that goes on behind the scenes.

like image 97
Travis Illig Avatar answered Dec 25 '22 22:12

Travis Illig