在ConfigureServices中请求实例

时间:2016-06-06 00:37:47

标签: dependency-injection asp.net-core

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

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

CustomFileProvider有一些依赖项(已全部配置),但在配置完所有服务后,如何让DI给我一个CustomFileProvider实例?

从我可以看到DI只注入构造函数,但在我的情况下,我需要“请在这里给我一个CustomFileProvider实例”选项。

1 个答案:

答案 0 :(得分:3)

如果您希望在配置某些选项时能够从容器中解析服务,则需要利用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<RazorViewEngineOptions>的其他已注册实例一起运行以设置选项对象。