Here\'s my problem: I have a container where I register concrete types as interfaces.
builder.RegisterType().As
If you are using the RegisterType to register your services this is possible. I wrote a quick test that should help you extract the data you need.
private interface IDeleteOrganization
{
}
private class DeleteOrganization : IDeleteOrganization
{
}
[TestMethod]
public void CanResolveConcreteType()
{
var builder = new ContainerBuilder();
builder.RegisterType()
.As();
using(var container = builder.Build())
{
var registration = container.ComponentRegistry
.RegistrationsFor(new TypedService(typeof (IDeleteOrganization)))
.SingleOrDefault();
if (registration != null)
{
var activator = registration.Activator as ReflectionActivator;
if (activator != null)
{
//we can get the type
var type = activator.LimitType;
Assert.AreEqual(type, typeof (DeleteOrganization));
}
}
}
}
You can very nicely encapsulate @Danielg's method so that you can let Autofac inject the type-list into a construtor. It requires you to implement the IRegistrationSource.
In my case I wanted to get all registered types derived from IConsoleCommand
like that:
public Help(TypeList<IConsoleCommand> commands)
{
_commands = commands;
}
I used a simple DTO-List to carry the types and the T
that I wanted to resolve them for:
public class TypeList<T> : List<Type>
{
public TypeList(IEnumerable<Type> types) : base(types)
{
}
}
The actual registration source is implemented as following where the <T>
from the TypeList<T>
is used to match the type of interface that is registered and that we want to retrieve.
internal class TypeListSource<T> : IRegistrationSource
{
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
if (service is IServiceWithType swt && typeof(TypeList<T>).IsAssignableFrom(swt.ServiceType))
{
var registration =
new ComponentRegistration(
id: Guid.NewGuid(),
activator: new DelegateActivator(swt.ServiceType, (context, p) =>
{
var types =
context
.ComponentRegistry
.RegistrationsFor(new TypedService(typeof(T)))
.Select(r => r.Activator)
.OfType<ReflectionActivator>()
.Select(activator => activator.LimitType);
return new TypeList<T>(types);
}),
services: new[] {service},
lifetime: new CurrentScopeLifetime(),
sharing: InstanceSharing.None,
ownership: InstanceOwnership.OwnedByLifetimeScope,
metadata: new Dictionary<string, object>()
);
return new IComponentRegistration[] {registration};
}
// It's not a request for the base handler type, so skip it.
else
{
return Enumerable.Empty<IComponentRegistration>();
}
}
public bool IsAdapterForIndividualComponents => false;
}
Finally you have to add it to the builder
with:
builder.RegisterSource(new TypeListSource<IConsoleCommand>());
Now Autofac can resolve the types with dependency injection.