I am trying to register on type (i.e. MyClass
) for multiple Keys (i.e. 3, 4, 5) in AutoFac.
So that, componentContext.ResolveKeyed<T>(3)
,componentContext.ResolveKeyed<T>(4)
and componentContext.ResolveKeyed<T>(5)
all return MyClass
instance.
I'm not sure how to do it as Keyed<IMyClass>()
requires the type and not the values.
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(type => type.IsAssignableTo<IMyClass>())
.Keyed<IMyClass>(type => type.GetCustomAttribute<MyCustomAttribute>().VALUES)
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
[MyCustomAttribute(3, 4, 5)]
class MyClass : IMyClass { }
class MyCustomAttribute : Attribute {
public int[] VALUES { get; set; }
public MyCustomAttribute(params int[] values) {
this.Values = values;
}
}
This is not supported in Autofac core, but you could easily make an extension method to do it for you.
public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle>
Keyed<TService>(
this IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle> registration,
Func<Type, object[]> serviceKeyMapping)
{
var serviceType = typeof(TService);
return registration
.AssignableTo(serviceType)
.As(t => serviceKeyMapping(t).Select(key => new KeyedService(key, serviceType)));
}
It should be roughly a drop-in replacement for what you're trying to do.
Autofac is pretty easy to extend this way by using the existing extension methods as a starting place for a lot of working examples. The one I put here is a very slight modification on the existing Keyed<T>
extension for assembly scanning. Since not every use case can possibly be covered, this is the "official solution" for filling gaps like this.