属性 使用 Autofac 和 ASP.NET 核心控制器注入

Property injection with Autofac and ASP.NET Core controller

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

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 我可以注入特定的 属性:

If you have one specific property and value to wire up, you can use the WithProperty() modifier: 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();
}

根据您的情况,您想要采用的方法确实没有必要。