简体   繁体   English

如何从 Asp.Net Core 的 ConfigureServices 方法中访问添加到 DI 容器的服务

[英]How to access a service added to DI container from inside Asp.Net Core's ConfigureServices method

The code sample below is from Asp.Net Core ConfigureServices method in Startup.cs.下面的代码示例来自 Startup.cs 中的 Asp.Net Core ConfigureServices方法。

I am first registering a singleton service called AppState .我首先注册了一个名为AppState的 singleton 服务。 Subsequent to that, I am configuring OpenIdConnect, and inside the OnTokenValidated lambda, I need to access the AppState service that I just registered in the DI container up above.之后,我正在配置 OpenIdConnect,在OnTokenValidated lambda 中,我需要访问我刚刚在上面的 DI 容器中注册的AppState服务。

What is the most elegant way of accessing the AppState service instance?访问AppState服务实例最优雅的方式是什么?

I would prefer to not call services.BuildServiceProvider() inside the ConfigureServices method if at all possible.如果可能的话,我宁愿不要在ConfigureServices方法中调用services.BuildServiceProvider()

services.AddSingleton<AppState>();

services.Configure<OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme, options =>
{
    options.Events = new OpenIdConnectEvents
    {
        OnTokenValidated = async ctx =>
        {
            //How to get access to instance of AppState, 
            //which was added to DI container up above
            AppState appState = //{get from DI somehow}; 
            appState.DoSomething();
        }
    };
});

EDIT: Using the answer below, I edited the code like so, but I can confirm that the OnTokenValidated event is not firing, as opposed to the code above in my original question, which does fire:编辑:使用下面的答案,我像这样编辑了代码,但我可以确认 OnTokenValidated 事件没有触发,而不是我原来的问题中的上面的代码,它确实触发了:

services.AddOptions<OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme)
            .Configure<IServiceScopeFactory>((options, sp) => {
                using (var scope = sp.CreateScope())
                {
                    options.Events = new OpenIdConnectEvents
                    {
                        OnTokenValidated = async ctx =>
                        {
                            var appState = scope.ServiceProvider.GetRequiredService<AppState>();

                            await appState.Dosomething();         
                        }
                    };
                }
            });

Use the TokenValidatedContext to get access to the current request service provider and resolve the service使用TokenValidatedContext访问当前请求服务提供者并解析服务

services
    .Configure<OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme, options => {
        options.Events = new OpenIdConnectEvents {
            OnTokenValidated = async ctx => {
                //Get access to instance of AppState, 
                //which was added to DI container up above
                AppState appState = ctx.HttpContext.RequestServices
                    .GetRequiredService<AppState>();
                await appState.DoSomething();

                //...
            }
        };
    });

You can access the DI service from the event context:您可以从事件上下文访问 DI 服务:

services.AddSingleton<AppState>();

services.Configure<OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme, options =>
{
    options.Events = new OpenIdConnectEvents
    {
        OnTokenValidated = async ctx =>
        {
            var appState = (AppState)ctx.HttpContext.RequestServices.GetService(typeof(AppState));
            appState.DoSomething();
        }
    };
});

Calling services.Configure<T> , adds an IConfigureOptions<T> to the service container that calls your action method;调用services.Configure<T> ,将IConfigureOptions<T>添加到调用您的操作方法的服务容器中; https://github.com/aspnet/Options/blob/master/src/Microsoft.Extensions.Options/OptionsServiceCollectionExtensions.cs#L72 https://github.com/aspnet/Options/blob/master/src/Microsoft.Extensions.Options/OptionsServiceCollectionExtensions.cs#L72

You can define your own implementation of IConfigureOptions<T> and inject any service you like.您可以定义自己的IConfigureOptions<T>实现并注入您喜欢的任何服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM