asp.net-core – 如何使用Autofac和ASP.NET Core在控制器上启用属性注入?

似乎没有一种简单的方法可以确保控制器具有属性注入.

解决这个问题的方法是单独注册所有控制器,这似乎有点失败了. [FromServices]属性是removed,他们特别提到它应该取决于各个IoC容器以确保发生这种情况.

我错过了一些明显的东西吗?查找所有可用的扩展方法,但没有找到任何内容,相同的问题和讨论论坛.

最佳答案 是的,为具有autofac的控制器设置属性注入有点棘手;)但这是它的工作原理.

使用ASP.NET Core(2.1),您首先需要在Startup.cs中将控制器注册为服务:

services.AddMvc().AddControllersAsServices();

否则财产注入将无法按照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.

然后,您需要通过populate向autofac容器构建器注册您的服务,然后您可以使用autofac容器注册您的控制器.

以下是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);
  }

附加.PropertiesAutowired()以允许属性注入非常重要!

现在另一件可能不明显的事情是,autofac的PropertiesAutowired并不会自动将服务的每个属性都视为属性注入的worty.

检查github source code中的DefaultPropertySelector,您将看到它将跳过非公开的:

if (!propertyInfo.CanWrite || propertyInfo.SetMethod?.IsPublic != true)
{
    return false;
}

因此,您可能需要创建一个自定义PropertySelector,它扩展DefaultPropertySelector,以便根据您自己的逻辑将属性注册为可注入的.所以你可以这样做:

var propSelector = new MyPropertySelector();
builder.RegisterType<MyController>().PropertiesAutowired(propSelector);

为了确保您不必总是记住每个控制器类,您还可以批量注册所有控制器:

builder.Populate(services);
var propSelector = new MyPropertySelector();
builder
  .RegisterAssemblyTypes(typeof(Controller).Assembly)
  .AssignableTo<Controller>()
  .InstancePerLifetimeScope()
  .PropertiesAutowired(propSelector);

希望这可以帮助 :)

点赞