在没有新的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>但它具有有限数量的可注入依赖项。第二种方式可以让你注入任意多,适合大量配置代码。


以上是在没有新的IServiceProvider实例的情况下指定自定义IModelBinderProvider?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>