问题
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:
- Register type in the container:
builder.RegisterType<Repository>().As<IRepository>();
- 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:
- Execute
AddControllersAsServices()
onservices.AddMvc()
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