Just learning Autofac and struggling to rgister a handful of named instances by convention.
public interface IFoo
{
string AutoFactName{ get; }
object DoSomething();
}
looking at this interface what i am trying to accomplish is something along these lines
builder.RegisterTypes()
.AssignableTo<IFoo>()
.As<IFoo>()
.Named<IFoo>(i => i.AutoFactName);
I have tried a few variations of something to this effect. the end goal is to dynamically register and resolve instances.
You should not need instances to register your types in Autofac. If you need information from your type it is better to use meta information like Attribute
. Something like that :
[FooMetadata("Foo1")]
public class Foo1 : IFoo
{ }
and then use this metadata while registering
builder.RegisterAssemblyTypes(assembly)
.AssignableTo<IFoo>()
.Named<IFoo>(t => t.GetCustomAttribute<FooMetadata>().Foo);
If you rely need to get the named type in your instance you can do it with a IRegistrationSource
public class NamedFooRegistrationSource : IRegistrationSource
{
public bool IsAdapterForIndividualComponents => false;
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
KeyedService keyedService = service as KeyedService;
if (keyedService == null || keyedService.ServiceKey.GetType() != typeof(String))
{
yield break;
}
IComponentRegistration registration = RegistrationBuilder
.ForDelegate(keyedService.ServiceType, (c, p) =>
{
Type foosType = typeof(IEnumerable<>).MakeGenericType(keyedService.ServiceType);
IEnumerable<IFoo> foos = (IEnumerable<IFoo>)c.Resolve(foosType);
foos = foos.Where(f => f.AutoFactName == (String)keyedService.ServiceKey).ToArray();
if (foos.Count() == 0)
{
throw new Exception($"no Foo available for {keyedService.ServiceKey}");
}
else if (foos.Count() > 1)
{
throw new Exception($"more than 1 Foo available for {keyedService.ServiceKey}");
}
else
{
return foos.First();
}
})
.Named((String)keyedService.ServiceKey, keyedService.ServiceType)
.CreateRegistration();
yield return registration;
}
}
and then register your Foo
this way :
builder.RegisterAssemblyTypes(assembly)
.AssignableTo<IFoo>()
.As<IFoo>();
builder.RegisterSource<NamedFooRegistrationSource>();