asp.net-mvc - 如何添加具有需要由 Autofac 解决的依赖项的自定义 ModelMetadataDetailsProvider?
问题描述
我正在尝试添加自定义 ModelMetadataDetailsProvider,但提供程序实现具有需要由服务提供程序 (Autofac) 解决的依赖项。如果我在 ConfigureServices 中添加 ModelMetadataDetailsProvider,我必须实例化并手动提供所有依赖项,其中一些是单例的并且是自动激活的,所以这不起作用...是否可以在 ConfigureServices 之外添加 ModelMetadataDetailsProvider?
看来这不能使用 DI 进行配置,所以我唯一能想到的就是在需要时使用 Service Locator Anti Pattern 来提供依赖项,而不是在构造函数中提供。有没有更可接受的方法来实现这一点?
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddMvcOptions(options => {
options.ModelMetadataDetailsProviders.Add(new MyProvider(???))
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddControllersAsServices();
services.AddAutofac();
ApplicationContainer = BuildContainer(services);
return new AutofacServiceProvider(ApplicationContainer);
}
public IContainer BuildContainer(IServiceCollection services)
{
var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterType<HttpContextAccessor>()
.As<IHttpContextAccessor>()
.SingleInstance();
builder.RegisterType<DataAccess>()
.As<IDataAccess>()
.WithParameter("connectionString", Configuration.GetConnectionString("DatabaseContext"))
.InstancePerLifetimeScope();
....
builder.RegisterType<D1>()
.As<ID1>();
builder.RegisterType<D2>()
.As<ID2>();
builder.RegisterType<D3>()
.As<ID3>();
builder.RegisterType<MyProvider>()
.As<IMyProvider>();
}
public interface IMyProvider : IDisplayMetadataProvider
{
...
}
public class MyProvider : IMyProvider
{
public MyProvider (ID1 d1, ID2 d2, ID3 d3)
{
...
}
public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
{
...
}
}
解决方案
IConfigureOptions<MvcOptions>
您可以通过创建一个实现接口的类来实现这一点:
public class AddCustomModelMetadataDetailsProvider : IConfigureOptions<MvcOptions>
{
private readonly MyCustomModelMetadataDetailsProvider _provider;
public AddCustomModelMetadataDetailsProvider(MyCustomModelMetadataDetailsProvider provider)
{
_provider = provider;
}
public void Configure(MvcOptions options)
{
options.ModelMetadataDetailsProviders.Add(_provider);
}
}
并在Configure
方法中注册它:
services.AddTransient<IConfigureOptions<MvcOptions>, AddCustomModelMetadataDetailsProvider>();
如您所见,这种方法的好处是您可以在AddCustomModelMetadataDetailsProvider
类中使用常规构造函数注入来获取您感兴趣的服务的实例。
ASP.NET 自动调用容器中注册Configure
的所有服务的方法。IConfigureOptions<MvcOptions>
因为创建这些类可能很耗时,所以 ASP.NET Core 2.2 引入了新的重载,允许您执行以下操作:
services
.AddOptions<MvcOptions>()
.Configure<MyCustomModelMetadataDetailsProvider>((options, customMetadataDetailsProvider) =>
{
options.ModelMetadataDetailsProviders.Add(customMetadataDetailsProvider);
});
在这种情况下,customMetadataDetailsProvider
将从容器中解析。
您最多可以包含 5 个服务来配置您的选项。请参阅此官方文档页面。
推荐阅读
- typescript - 嵌套对象类型的 TypeScript keyof
- docker - GKE Autopilot Ingress 部署后 5-15 分钟返回 502 错误
- types - Python 3 中不同格式的返回类型
- python - 最好使用语法或正则表达式解析表格
- django - 视图 HomePage.views.signin 未返回 HttpResponse 对象。它返回 None 而不是
- regex - webpack-cli SyntaxError: 无效的正则表达式: /(\p{大写字母}+|\p{小写字母}|\d)(\p{大写字母}+)/:
- java - Spring Boot POST 请求验证
- python - 错误:Google Colab(>7GB)中的“找不到中央目录的开始;zipfile 损坏”
- java - 属性“mainMergedManifest”不存在
- reactor-netty - 如果名称服务器提供多个IP地址,如何配置netty HttpClient重试建立连接