Search code examples
c#dependency-injectionautofac

Dynamic TypeRegistration in Autofac C# using an Unknown type


I'm trying to create an autofac container that is passed a list of services to register for use in across a number of projects.

I've got the base container builder with all the required types across a number of properties, however I need to then inject a list of services from the class using this base.

what I have:

        private void buildAutofacContainer(IServiceCollection services, List<ServiceDescriptor> servicesToAdd)
    {
        var builder = new ContainerBuilder();
        builder.Register(x => new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddEnvironmentVariables()
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .Build()).As<IConfigurationRoot>().SingleInstance();
        builder.RegisterType<LoggingInterceptor>();
        builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>();
        builder.RegisterType<ApplicationEngine>().As<IApplicationEngine>();
        builder.RegisterType<ApplicationSettings>().As<IApplicationSettings>();
        builder.RegisterType<PortalUnitOfWorkFactory>().As<IPortalUnitOfWorkFactory>();
        builder.RegisterType<DataConnectionService>().As<IDataConnectionService>();
        builder.Populate(services);
        this.Container = builder.Build();
    }

What I'm trying to do:

            servicesToAdd.ForEach(o =>
        {
            object concrete = o.ImplementationInstance;
            Type type = o.ImplementationType;
            builder.RegisterType<concrete>().As<type>();
        });

any help would be greatly appreciated


Solution

  • I'm not sure if I understand you correctly. If the goal was to add list of service descriptors to your Autofac container/container builder, you could populate those descriptors into services as IServiceCollection is a collection of service descriptors.

        void BuildBaseContainer(IServiceCollection services, List<ServiceDescriptor> servicesToAdd)
        {
            foreach (var descriptor in servicesToAdd)
            {
                services.Add(descriptor);
            }
    
            var builder = new Autofac.ContainerBuilder();
            builder.Populate(servicesToAdd);
            this.Container = builder.Build();
        }
    

    Or if your goal was to register an object/instance as an type known only at runtime, you could use the non-generic As(params Type[]) method and pass the type to the method:

    // Could also use descriptor.ImplementationType depends on your ServiceDescriptor.
    var concreteType = descriptor.ImplementationInstance.GetType();
    builder.RegisterType(concreteType)
            .As(descriptor.ImplementationType) // As implementation type
            .As(<other type>) // As any other type
            .AsSelf() // As the object's type
            .As(descriptor.ImplementationInstance.GetType()) // As the implementation instance type
            .AsImplementedInterfaces() // As all implemented interface types
            ;