在 IServiceCollection 扩展中获取服务 [英] Get a service in a IServiceCollection extension

查看:46
本文介绍了在 IServiceCollection 扩展中获取服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个扩展

public static class ServiceCollectionExtensions
{
    public static IServiceCollection MyExtension(this IServiceCollection serviceCollection)
    {
      ...
    }
}

我需要从这样的服务中获取信息:

and I need to get information from a service like this:

services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
    {
        var myService = <<HERE>>();
        options.TokenValidationParameters = this.GetTokenValidationParameters(myService);
    });

我该怎么做?

我试图在 var serviceProvider = services.BuildServiceProvider(); 之后获取 ServiceProvider 然后我发送了 serviceProvider,但这并没有不行..

I tried to get the ServiceProvider after var serviceProvider = services.BuildServiceProvider(); and then I send the serviceProvider, but this doesn't work..

推荐答案

在您调用 services.AddSomething() 时,服务 provider 尚未构建从服务集合呢.所以你不能在那个时候实例化一个服务.幸运的是,有一种方法可以在使用依赖注入的同时配置服务.

At the time you are calling services.AddSomething(), the service provider has not been built from the service collection yet. So you cannot instantiate a service at that time. Fortunately, there is a way to configure services while using dependency injection.

当你执行 services.AddSomething(options => ...) 时,通常会发生一定数量的服务将注册到服务集合中.然后传入的配置action也会以一种特殊的方式注册,这样当服务稍后被实例化时,它就能够执行那个配置操作以应用配置.

When you do services.AddSomething(options => …) what usually happens is that a certain amount of services will be registered with the service collection. And then the passed configuration action will also be registered in a special way, so that when the service is later instantiated, it will be able to execute that configuration action in order to apply the configuration.

为此,您需要实现 IConfigureOptions(或实际上 IConfigureNamedOptions 用于身份验证选项)并将其注册为单例.出于您的目的,这可能如下所示:

For that, you need to implement IConfigureOptions<TOptions> (or actually IConfigureNamedOptions<TOptions> for authentication options) and register it as a singleton. For your purpose, this could look like this:

public class ConfigureJwtBearerOptions : IConfigureNamedOptions<JwtBearerOptions>
{
    private readonly IMyService _myService;

    public ConfigureJwtBearerOptions(IMyService myService)
    {
        // ConfigureJwtBearerOptionsis constructed from DI, so we can inject anything here
        _myService = myService;
    }

    public void Configure(string name, JwtBearerOptions options)
    {
        // check that we are currently configuring the options for the correct scheme
        if (name == JwtBearerDefaults.AuthenticationScheme)
        {
            options.TokenValidationParameters = myService.GetTokenValidationParameters();
        }
    }

    public void Configure(JwtBearerOptions options)
    {
        // default case: no scheme name was specified
        Configure(string.Empty, options);
    }
}

然后您在 Startup 中注册该类型:

You then register that type in your Startup:

services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    // add JwtBearer but no need to pass options here
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, configureOptions: null);

// instead we are registering our configuration type to configure it later
services.AddSingleton<IConfigureOptions<JwtBearerOptions>, ConfigureJwtBearerOptions>();

这实际上和你只做 services.AddJwtBearer(scheme, options => { ... }) 时发生的完全一样,只是抽象出来的,所以你不需要关心关于它.但是通过手动操作,您现在可以拥有更多权力并访问完整的依赖注入服务提供者.

This is actually the exact same thing that happens when you just do services.AddJwtBearer(scheme, options => { … }), just abstracted away, so you don’t need to care about it. But by doing it manually, you now have more power and access to the full dependency injection service provider.

这篇关于在 IServiceCollection 扩展中获取服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆