There doesn't really seem to be an easy way to make sure the controllers have property injection.
A way around it would be to register all controllers individually, which seems to defeat the purpose a bit. The [FromServices] attribute is removed and they specifically mention it should be up to the individual IoC containers to make sure this happens.
Am I missing something glaringly obvious? Looked for all available extension methods but didn't find anything, same for issues and the discussion forum.
解决方案
Yeah, setting up property injection for controllers with autofac is a bit tricky ;) but here is how it works.
With ASP.NET Core (2.1) you first need to register your controllers as services in your Startup.cs:
services.AddMvc().AddControllersAsServices();
otherwise property injection won't work as quoted from the autofac docs:
By default, ASP.NET Core will resolve the controller parameters from the container but doesn’t actually resolve the controller from the container. This usually isn’t an issue but it does mean: [...] Special wiring that you may have done during registration of the controller (like setting up property injection) won’t work.
You then need to register your services with the autofac container builder via populate and afterwards you can register your controllers with the autofac container.
Here is a shortened code excerpt from the autofac docs:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddControllersAsServices();
var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterType().PropertiesAutowired();
this.ApplicationContainer = builder.Build();
return new AutofacServiceProvider(this.ApplicationContainer);
}
It is important that you append .PropertiesAutowired() to allow property injection!
Now another thing to mention which may not be obvious is that autofac's PropertiesAutowired does not automatically consider every property of your service to be worty for property injection.
Checkout the DefaultPropertySelector from the github source code and you will see it will skip non-public ones:
if (!propertyInfo.CanWrite || propertyInfo.SetMethod?.IsPublic != true)
{
return false;
}
So you may need to create a custom PropertySelector that extends the DefaultPropertySelector in order to register the properties as being injectable based on your own logic. So you could do something like this:
var propSelector = new MyPropertySelector();
builder.RegisterType().PropertiesAutowired(propSelector);
In order to make sure that you do not always have to remember each single controller class, you can also register all your controllers in bulk:
builder.Populate(services);
var propSelector = new MyPropertySelector();
builder
.RegisterAssemblyTypes(typeof(Controller).Assembly)
.AssignableTo()
.InstancePerLifetimeScope()
.PropertiesAutowired(propSelector);
Hope this helps :)