Search code examples
c#.netautofac

How to get a type from Autofac Registrations used for registration


How can I get type that was used to register class in container from container.ComponentRegistry.Registrations?

    // I have some types like

    interface IBase { }
    interface IA : IBase { }
    interface IB : IBase { }

    class A : IA { }
    class B : IB { }

    class Program
    {
        static void Main(string[] args)
        {
            var builder = new ContainerBuilder();

            // Registering types as interface implementations
            builder.RegisterType<A>().As<IA>();
            builder.RegisterType<B>().As<IB>();

            var c = builder.Build();


            // Trying to get all registered types assignable to IBase
            var types = c.ComponentRegistry.Registrations
                .Where(r => typeof(IBase).IsAssignableFrom(r.Activator.LimitType))
                .Select(r => r.Activator.LimitType); // Returns A insted of IA

            // Trying to Resolve all types
            types.Select(t => c.Resolve(t) as IBase).ToList();
        }
    }

Because .Activator.LimitType returns type A insted of type IA which was used in container, i getting an Exception

Autofac.Core.Registration.ComponentNotRegisteredException : The requested service 'A' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.


Solution

  • One approach is to ensure your register A not just against IA but also against IBase (and the same for B).

    Then resolving IEnumerable<IBase> will find both A and B:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Autofac;
    
    namespace WatCode
    {
        interface IBase { }
        interface IA : IBase { }
        interface IB : IBase { }
    
        class A : IA { }
        class B : IB { }
    
        class Program
        {
            static void Main(string[] args)
            {
                var builder = new ContainerBuilder();
    
                // Registering types as interface implementations
                builder.RegisterType<A>().AsImplementedInterfaces(); // register against IA and IBase
                builder.RegisterType<B>().AsImplementedInterfaces(); // register against IB and IBase
    
                var c = builder.Build();
    
                var matching = c.Resolve<IEnumerable<IBase>>();
    
                Console.WriteLine(matching.Count());
            }
    
        }
    }
    

    Above will write 2 to the console since it finds both matches.