在没有新的IServiceProvider实例的情况下指定自定义IModelBinderProvider?
我的类中有以下代码Startup,它使用IModelBinderProvider. 大多数输入格式化程序需要一个ILogger实例,所以我需要有一个ILoggerFactory,为此我想使用配置的一个,它以指定的详细程度记录到指定的目的地。我正在ILoggerFactory从一个新建的IServiceProvider:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddMvcCore(
options =>
{
...
var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
options.ModelBinderProviders.Clear();
options.ModelBinderProviders.Add(
new MyCustomBinderProvider(options.InputFormatters, loggerFactory)
);
...
}
);
...
}
问题是我收到以下警告:
Startup.cs(62, 43): [ASP0000] Calling 'BuildServiceProvider' from application code results in an
additional copy of singleton services being created. Consider alternatives such
as dependency injecting services as parameters to 'Configure'.
我看了一下这个问题:Resolving instances with ASP.NET Core DI from inside ConfigureServices。但是,我的代码是 的 lambda AddMvcCore,它正在配置options对象。换句话说,在Configure调用 时,MVC 选项已经定义。
有没有办法在这里做正确的事情,即防止无关的实例IServiceProvider?
回答
在配置选项时有几种方法可以注入服务。第一种方法是使用OptionsBuilder<TOptions>可以通过使用扩展方法获得的an IServiceCollection.AddOptions,如下所示:
services.AddOptions<MvcOptions>()
//first arg is always of TOptions,
//injectable dependencies start from the second arg
.Configure((MvcOptions o, ILoggerFactory loggerFactory) => {
o.ModelBinderProviders.Insert(0,
new MyCustomBinderProvider(o.InputFormatters, loggerFactory)
);
});
第二种方法是实现一个IConfigureOptions<TOptions>(或IPostConfigureOptions<TOptions>),如下所示:
public class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
readonly ILoggerFactory _loggerFactory;
public ConfigureMvcOptions(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
public void Configure(MvcOptions options)
{
options.ModelBinderProviders.Insert(0,
new MyCustomBinderProvider(options.InputFormatters, _loggerFactory)
);
}
}
//then configure it like this:
services.ConfigureOptions<ConfigureMvcOptions>();
第一种方法很方便,因为您不必为实现而创建单独的类,IConfigureOptions<Options>但它具有有限数量的可注入依赖项。第二种方式可以让你注入任意多,适合大量配置代码。
THE END
二维码