How to enable property injection on controllers using Autofac and ASP.NET Core?

浪尽此生 提交于 2019-12-10 17:14:43

问题


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.


回答1:


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<MyController>().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<MyController>().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<Controller>()
  .InstancePerLifetimeScope()
  .PropertiesAutowired(propSelector);

Hope this helps :)



来源:https://stackoverflow.com/questions/37299191/how-to-enable-property-injection-on-controllers-using-autofac-and-asp-net-core

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