在ConfigureServices
内,我正在设置一些服务(这是有效的)。在同一方法中,我正在尝试配置自定义文件提供程序(用于Razor)。它看起来像这样:
services.AddMvc()
.AddRazorOptions(options =>
{
options.FileProvider = new CustomFileProvider(???);
});
CustomFileProvider
有一些依赖项(已全部配置),但在配置完所有服务后,如何让DI给我一个CustomFileProvider
实例?
从我可以看到DI只注入构造函数,但在我的情况下,我需要“请在这里给我一个CustomFileProvider
实例”选项。
答案 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>
的其他已注册实例一起运行以设置选项对象。