«AddOptions <T>.Configure ()» не работает, когда «services.AddTransient () "делает? - PullRequest
3 голосов
/ 03 марта 2020

Я пытаюсь настроить Аутентификацию IdentityServer4 с использованием строго типизированного объекта конфигурации.

Документация шаблона параметров от Microsoft говорит:

Вы можете получить доступ к другим услуги от внедрения зависимостей при настройке параметров двумя способами:

  • Передача делегата конфигурации в Configure on OptionsBuilder. OptionsBuilder предоставляет перегрузки Configure, которые позволяют использовать до пяти служб для настройки параметров:

    services.AddOptions<MyOptions>("optionalName")
        .Configure<Service1, Service2, Service3, Service4, Service5>(
            (o, s, s2, s3, s4, s5) => 
                o.Property = DoSomethingWith(s, s2, s3, s4, s5));
    
  • Создайте свой собственный тип, который реализует IConfigureOptions или IConfigureNamedOptions, и зарегистрируйте тип как службу.

Мы рекомендуем передать делегат конфигурации в Configure, поскольку создание службы более сложное. Создание собственного типа эквивалентно тому, что делает среда для вас, когда вы используете Configure. Вызов Configure регистрирует временные обобщенные IConfigureNamedOptions, у которых есть конструктор, который принимает указанные типы родовых c типов обслуживания.

Я посмотрел исходный код для OptionsBuilder, и он выглядит как документация точна в том, что эти два метода функционально эквивалентны, но метод делегата конфигурации не работает для IdentityServer4, поэтому я задаю этот вопрос как еще один из любопытств.

Это не работает, когда я добавляю Startup.cs:

services
    .AddOptions<IdentityServerAuthenticationOptions>()
    .Configure<IdentityServerConfiguration>((options, configuration)) =>
    {
        options.Audience = configuration.Audience
        // etc.
    });

services
    .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication();

Однако, создав класс, как показано ниже:

public sealed class ConfigureOptions : IConfigureNamedOptions<IdentityServerAuthenticationOptions>
{
    private readonly IdentityServerConfiguration _configuration;

    public ConfigureOptions(IdentityServerConfiguration configuration)
    {
        _configuration = configuration;
    }

    public void Configure(string name, IdentityServerAuthenticationOptions options)
    {
        options.ApiName = _configuration.Audience;
        // etc.
    }

    public void Configure(IdentityServerAuthenticationOptions options)
    {
        options.ApiName = _configuration.Audience;
        // etc.
    }
}

И добавив его к Startup.cs, например:

services
    .AddTransient<IConfigureOptions<IdentityServerAuthenticationOptions>, ConfigureOptions>();

services
    .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication();

Заставляет его работать идеально.

Кто-нибудь знает, почему он так себя ведет?

...