【问题标题】:Request instance within ConfigureServicesConfigureServices 中的请求实例
【发布时间】:2016-06-06 00:37:46
【问题描述】:

ConfigureServices 内,我正在设置一些服务(这可行)。在相同的方法中,我正在尝试配置自定义文件提供程序(用于 Razor)。它看起来像这样:

services.AddMvc()
        .AddRazorOptions(options =>
        {
            options.FileProvider = new CustomFileProvider(???);
        });

CustomFileProvider 有一些依赖项(都已配置),但是在配置完所有服务后,我如何要求 DI 给我一个 CustomFileProvider 的实例?

据我所知,DI 仅注入构造函数,但在我的情况下,我需要一个“请在此处给我一个 CustomFileProvider 的实例”选项。

【问题讨论】:

  • 您无法在 ConfigureServices 中解析,因为容器是在调用 ConfigureServices 和调用 Configure 之前构建的。如果你对文件提供者没有非常复杂的依赖结构,你应该手动注入它们。

标签: dependency-injection asp.net-core


【解决方案1】:

如果您希望能够在配置某些选项时从容器解析服务,则需要利用 IConfigureOptions<TOption> 基础架构,大多数 MVC 使用它来设置选项默认值。示例见RazorViewEngineOptionsSetup

首先,将您需要的服务添加到集合中:

services.AddSingleton<IDependency1, Dependency1>();
services.AddSingleton<IDependency2, Dependency2>();

然后,实现设置类:

public class CustomFileProviderRazorViewEngineOptionsSetup : ConfigureOptions<RazorViewEngineOptions>
{
    public CustomFileProviderRazorViewEngineOptionsSetup(IServiceProvider serviceProvider)
        : base(options => ConfigureRazor(options, serviceProvider))
    {
    }

    private static void ConfigureRazor(RazorViewEngineOptions options, IServiceProvider serviceProvider)
    {
        // Alternative 1 - Resolve each service and new up the instance.
        var dependency1 = serviceProvider.GetService<IDependency1>();
        var dependency2 = serviceProvider.GetService<IDependency2>();

        options.FileProviders.Add(new CustomFileProvider(dependency1, dependency2));

        // Alternative 2 - Same as alternative 1, but with moar magic ;)
        options.FileProviders.Add(ActivatorUtilities.CreateInstance<CustomFileProvider>(serviceProvider));

        // Alternative 3 - Just resolve CustomFileProvider from the service provider.
        // This requires it to be registered first, of course.
        options.FileProviders.Add(serviceProvider.GetService<CustomFileProvider>());
    }
}

这是从容器中解析的,因此它允许您注入一个IServiceProvider,它可以再次用于解析您需要的服务。您可以选择将 CustomFileProvider 添加到容器中并直接解决它,就像在替代方案 3 中一样。

最后,将设置类添加到服务集合中:

services.TryAddEnumerable(
    ServiceDescriptor.Transient<
        IConfigureOptions<RazorViewEngineOptions>,
        CustomFileProviderRazorViewEngineOptionsSetup>());

这会将设置添加到选项构建器管道,这意味着它将与IConfigureOptions&lt;RazorViewEngineOptions&gt; 的其他注册实例一起运行以设置选项对象。

【讨论】:

  • +1。您甚至可以使用options.FileProviders.Add(ActivatorUtilities.CreateInstance(serviceProvider, typeof(CustomFileProvider))) 来稍微简化实例化。
  • 是的。添加了几个替代方案:)
猜你喜欢
  • 2015-10-30
  • 2018-05-12
  • 2021-01-06
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多