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

4
下面的代码示例来自于Startup.cs文件中Asp.Net Core的ConfigureServices方法。
我首先注册了一个名为AppState的单例服务。随后,我配置了OpenIdConnect,在OnTokenValidated lambda内部,我需要访问DI容器中刚刚注册的AppState服务。
如何最优雅地访问AppState服务实例?
如果可能的话,我更愿意避免在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();
        }
    };
});

编辑:使用下面的答案,我修改了代码,但是我可以证实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();         
                        }
                    };
                }
            });

@Nkosi 感谢您的回答...您能否请教我可能做错了什么。我已经用新代码编辑了我的问题,但 OnTokenValidated 没有触发。 - user2202866
3个回答

9
使用 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();

                //...
            }
        };
    });

这帮助我更接近类似的问题,但我在这里发现的是,当使用razor从主页登录WebApp时,OnTokenValidated事件似乎只会触发一次。我正在尝试找出如何在从任何受保护的页面或资源启动登录过程时触发此事件。 - OJB1

4
您可以从事件上下文中访问 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();
        }
    };
});

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接