使用 Autofac 和 ASP.NET Core 控制器进行属性注入

问题描述

我的控制器类只有一个依赖项,例如:

public class UserController : ControllerBase {
  public UserController(IMediator mediator) => _mediator = mediator;
  private readonly IMediator _mediator;
}

但这必须在我所有的控制器中复制。我更喜欢进行属性注入,所以我可以像这样清理它:

public abstract class MyControllerBase : ControllerBase {
  public IMediator Mediator { get; init; }  // use init so container resolves this and cannot be changed later
}

public class UserController : MyControllerBase {
}

为了让它发挥作用,我关注了 the docs

我更改了我的 Startup.ConfigureServices()

services.AddControllers().AddControllersAsServices();

我在 Startup.ConfigureContainer(ContainerBuilder builder)注册了控制器:

builder
  .RegisterassemblyTypes(typeof(Startup).Assembly)
  .Assignableto<MyControllerBase>()
  .InstancePerLifetimeScope()
  .PropertiesAutowired();

那行得通。

但是docs say我可以注入一个特定的属性

如果您有一个特定的属性和值需要连接,您可以使用 Withproperty() 修饰符:builder.RegisterType<A>().WithProperty("PropertyName",propertyValue);

所以我必须更改我的代码

var types =
  typeof(Startup).Assembly
  .GetExportedTypes()
  .Where(type => typeof(MyControllerBase).IsAssignableFrom(type))
  .ToArray();

foreach (var type in types)
  builder.RegisterType(type).WithProperty(nameof(MyControllerBase.Mediator),propertyValue);

如何从容器动态解析 propertyValue。并且,容器会在控制器类中注入任何其他属性,还是只会注入该属性

解决方法

您尝试执行的操作不适合该场景。 正如您已经遇到的那样,如果在设置时已知特定值,则与动态分辨率无关。

我建议在容器将解析依赖项并设置属性之前保持它的工作方式。

//...

public void ConfigureContainer(ContainerBuilder builder) { 
    var types =
        typeof(Startup).Assembly
        .GetExportedTypes()
        .Where(type => typeof(MyControllerBase).IsAssignableFrom(type))
        .ToArray();
    
    
    builder.RegisterTypes(types).PropertiesAutowired();
}

考虑到您的情况,您想要采用的方法确实没有必要。