Get a list of all registered objects implementing a certain interface

If you have

container.Register(c => new A()).As<ISomeInterface>();
container.Register(c => new B()).As<ISomeInterface>();

Then when you do

var classes = container.Resolve<IEnumerable<ISomeInterface>>();

You will get a variable that is a list of ISomeInterface, containing A and B


I was looking for a similar solution for registrations done as follows:

builder.RegisterType<Bamboo>().As<IExoticTree>();
// and/or
builder.RegisterType<SolidOak>().Keyed<IMountainTree>(key);

where IExoticTree and IMountainTree inherit from a common ITree interface.

With those, the service type (e.g. registered interface) is different from the LimitType and hence, the proposed solution is not applicable.

I got inspired by the accepted solution to manage these as well with the following code:

IEnumerable<ITree> instances = scope.ComponentRegistry.Registrations
                                                      .Where(r => typeof(ITree).IsAssignableFrom(r.Activator.LimitType))
                                                      .Select(r => r.Services.First())
                                                      .Select(s => scope.ResolveService(s) as ITree)
                                                      .Distinct();

Hope it helps someone ^^


Here is how I did it.

var l = Container.ComponentRegistry.Registrations
          .SelectMany(x => x.Services)
          .OfType<IServiceWithType>()
          .Where(x => 
                 x.ServiceType.GetInterface(typeof(ISomeInterface).Name) != null)
          .Select(c => (ISomeInterface) c.ServiceType);

Just tried this, works and does not depend on lifetime context:

Enumerate types using Activator instead

var types = con.ComponentRegistry.Registrations
     .Where(r => typeof(ISomeInterface).IsAssignableFrom(r.Activator.LimitType))
     .Select(r => r.Activator.LimitType);

Then to resolve:

IEnumerable<ISomeInterface> lst = types.Select(t => con.Resolve(t) as ISomeInterface);

Tags:

Autofac