属性 使用 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();
}
根据您的情况,您想要采用的方法确实没有必要。
我的控制器类只有一个依赖项,例如:
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();
}
根据您的情况,您想要采用的方法确实没有必要。