如何使用Autofac和ASP.NET Core在控制器上启用属性注入? [英] How to enable property injection on controllers using Autofac and ASP.NET Core?

查看:477
本文介绍了如何使用Autofac和ASP.NET Core在控制器上启用属性注入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎真的不是一种简单的方法来确保控制器具有属性注入.

There doesn't really seem to be an easy way to make sure the controllers have property injection.

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

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.

推荐答案

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

Yeah, setting up property injection for controllers with autofac is a bit tricky ;) but here is how it works.

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

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:

默认情况下,ASP.NET Core会从容器中解析控制器参数,但实际上不会从容器中解析控制器.这通常不是问题,但这意味着:[...] 您在控制器注册过程中可能进行的特殊接线(例如,设置属性注入)将不起作用. >

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容器中注册控制器.

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.

这是 autofac的简短代码摘录文档:

  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(),以允许进行属性注入!

It is important that you append .PropertiesAutowired() to allow property injection!

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

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;
}

因此,您可能需要创建扩展DefaultPropertySelector的自定义PropertySelector,以便根据您自己的逻辑将属性注册为可注入的.因此,您可以执行以下操作:

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);

希望这会有所帮助:)

这篇关于如何使用Autofac和ASP.NET Core在控制器上启用属性注入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆