Autofac property injection in .NET Core MVC project

Viewed 1515

I have a controller with ILol type property and Lol class implementing ILol.

public class UniversityController : Controller
{
    public ILol Lol { get; set; }

    public IActionResult Index()
    {
        ViewData["Header"] = "Hello, world!";
        ViewData["NullCheck"] = Lol == null ? "It's null" : Lol.GetLol();

        return View();
    }
}

I try to use Property injection with Autofac in this manner (a part of my Startup class):

public IContainer ApplicationContainer { get; private set; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        // Dependency resolving.
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        ContainerBuilder builder = new ContainerBuilder();

        builder.RegisterType<Lol>().As<ILol>().PropertiesAutowired().InstancePerLifetimeScope();
        builder.Populate(services);

        IContainer container = builder.Build();

        ApplicationContainer = container;

        return new AutofacServiceProvider(container);
    }

It does not work. The property is null in runtime. Though constructor injection works properly.

1 Answers

You have to specify in which controllers needed to use Properties Injection:

 var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
            .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
 builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();

And call AddControllersAsServices():

services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddControllersAsServices();

If you need to register property injection just register more types PropertiesAutowired() in the builder.

And ConfigureServices will look like this:

public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        // Dependency resolving.
        services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
        .AddControllersAsServices();

        ContainerBuilder builder = new ContainerBuilder();
        builder.Populate(services);//Autofac.Extensions.DependencyInjection

        builder.RegisterType<Lol>().As<ILol>().PropertiesAutowired().InstancePerLifetimeScope();
        builder.Populate(services);

        var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
            .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
        builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();

        IContainer container = builder.Build();

        ApplicationContainer = container;

        return new AutofacServiceProvider(container);
    }
Related