问题描述
在ConfigureServices
内,我正在设置许多服务(这可行).我尝试使用相同的方法(针对Razor)配置自定义文件提供程序.看起来像这样:
Within ConfigureServices
I'm setting up a number of services (this works). In the same method I'm trying to configure a custom file provider (for Razor). It looks like this:
services.AddMvc()
.AddRazorOptions(options =>
{
options.FileProvider = new CustomFileProvider(???);
});
CustomFileProvider
有一些依赖项(都已配置),但是在配置完所有服务之后,如何立即要求DI给我一个CustomFileProvider
实例?
CustomFileProvider
has a few dependencies (that are all configured), but how can I ask the DI to give me an instance of CustomFileProvider
right after all the services have been configured?
从我的角度来看,DI仅注入构造函数,但就我而言,我需要一个请在此处给我CustomFileProvider
的实例"选项.
From what I can see the DI only injects in constructors, but in my case I need a "please give me an instance of CustomFileProvider
right here" option.
推荐答案
如果您希望能够在配置某些选项的同时从容器中解析服务,则需要利用IConfigureOptions<TOption>
基础结构,大多数MVC都使用该基础结构设置选项默认值.请参阅 RazorViewEngines >例如.
If you want to be able to resolve services from the container while configuring some options, you need to leverage the IConfigureOptions<TOption>
infrastructure, which most of MVC uses to set up the option defaults. See RazorViewEngineOptionsSetup for an example.
首先,将所需的服务添加到集合中:
First, add the services you need to the collection:
services.AddSingleton<IDependency1, Dependency1>();
services.AddSingleton<IDependency2, Dependency2>();
然后,实现安装程序类:
Then, implement the setup class:
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中一样.
This is resolved from the container, so it'll allow you to inject an IServiceProvider
, which can again be used to resolve the services you need. You could optionally add the CustomFileProvider
to the container and resolve that directly instead, like in alternative 3.
最后,将安装程序类添加到服务集合:
Finally, add the setup class to the service collection:
services.TryAddEnumerable(
ServiceDescriptor.Transient<
IConfigureOptions<RazorViewEngineOptions>,
CustomFileProviderRazorViewEngineOptionsSetup>());
这会将设置添加到选项构建器管道,这意味着它将与IConfigureOptions<RazorViewEngineOptions>
的其他已注册实例一起运行以设置选项对象.
This will add the setup to the options builder pipeline, which means it'll run with the other registered instances of IConfigureOptions<RazorViewEngineOptions>
to setup the options object.
这篇关于ConfigureServices中的请求实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!