How to use Property Injection in MVC Core and AutoFac

北城余情 提交于 2019-12-23 10:51:40

问题


I can use Constructor Parameter Injection easily In MVC Core. But Property Injection is not supported.I try use AutoFac but fail too.
So how to use Property Injection in MVC Core.
Here is the code with AutoFac

services.AddMvc();
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Test2>().As<ITest>();
builder.RegisterType<HomeController>().PropertiesAutowired();
builder.Populate(services);
var container = builder.Build();
//The following code works
HomeController test2 = container.Resolve<HomeController>();
return new AutofacServiceProvider(container); 

回答1:


In dotnet core, you need to make the following changes to make Autofac work: Add a public Autofac IContainer in your application Startup.cs

public IContainer ApplicationContainer { get; private set; }

Change ConfigureServices in Startup.cs to return IServiceProvider, do all your registrations, populate the framework services in your container by using builder.Populat(services);. Please note that there is no need for you to do builder.RegisterType<HomeController>().PropertiesAutowired();

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    builder.Populate(services);
    ApplicationContainer = container;
    return new AutofacServiceProvider(ApplicationContainer);
}

You will also need to make sure you dispose the container on application stopped by doing this in your Configure method.

public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime)
{
    app.UseMvc();           
    appLifetime.ApplicationStopped.Register(() => ApplicationContainer.Dispose());
}

After you do this - your controllers should automatically get the properties autowired.




回答2:


Property injection requires some additional setup. Let's Assume in your case we have this hierarchy of classes:

    public class HomeController 
    {
        public ITest Test {get; set;}            
    }    
    public class Test : ITest
    {
        public IRepository Repository {get;set;}    
    }
    public class Repository: IRepository
    {
    }

The first things needed to be done are changing the return type to IServiceProvider for ConfigureServices(IServiceCollection services) and building new container using Populate method from 'Autofac.Extensions.DependencyInjection' method in order to return AutofacServiceProvider

New ConfigureServices method:

public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().AddControllersAsServices();
        ContainerBuilder builder = new ContainerBuilder();

        builder.Populate(services);//Autofac.Extensions.DependencyInjection

        /*Here we are going to register services for DI*/

        return new AutofacServiceProvider(builder.Build());
    }

Next step is registration of classes in DI container. Property-injection for 'service classes' requires less action than for 'controllers'. To setup property injection for service classes you just need to:

  1. Register type in the container: builder.RegisterType<Repository>().As<IRepository>();
  2. Register type in which you are going to inject dependencies through properties with PropertiesAutowired(): builder.RegisterType<Test>.As<ITest>().PropertiesAutowired()

To setup property injection for a controllers you need a little more steps:

  1. Execute AddControllersAsServices() on services.AddMvc()
  2. Regiser DI for controllers with call of PropertiesAutowired() for all controllers:

    //in case you just need to allow registration for several specific controllers change this line
    var controllersTypesInAssembly = typeof(Startup).Assembly
            .GetExportedTypes()
            .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
    
    builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired(); 
    

As a result here is ConfigureServices() for predetermined hierarchy:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddControllersAsServices();
    ContainerBuilder builder = new ContainerBuilder();

    builder.Populate(services);//Autofac.Extensions.DependencyInjection

    builder.RegisterType<Repository>().As<IRepository>()
        .InstancePerLifetimeScope();
    var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
        .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();

    builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
    builder.RegisterType<Test>().As<ITest>().PropertiesAutowired();
    return new AutofacServiceProvider(builder.Build());
}


来源:https://stackoverflow.com/questions/50479616/how-to-use-property-injection-in-mvc-core-and-autofac

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!