Как разрешить экземпляр внутри ConfigureServices в ядре ASP.NET

Можно ли разрешить экземпляр IOptions<AppSettings> из метода ConfigureServices в Startup? Обычно вы можете использовать IServiceProvider для инициализации экземпляров, но у вас его нет на этом этапе, когда вы регистрируете службы.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(
        configuration.GetConfigurationSection(nameof(AppSettings)));

    // How can I resolve IOptions<AppSettings> here?
}

Ответ 1

Вы можете создать поставщика услуг с помощью метода BuildServiceProvider() на IServiceCollection:

public void ConfigureService(IServiceCollection services)
{
    // Configure the services
    services.AddTransient<IFooService, FooServiceImpl>();
    services.Configure<AppSettings>(configuration.GetSection(nameof(AppSettings)));

    // Build an intermediate service provider
    var sp = services.BuildServiceProvider();

    // Resolve the services from the service provider
    var fooService = sp.GetService<IFooService>();
    var options = sp.GetService<IOptions<AppSettings>>();
}

Для этого вам нужен пакет Microsoft.Extensions.DependencyInjection.


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

var appSettings = new AppSettings();
configuration.GetSection(nameof(AppSettings)).Bind(appSettings);

Эта функциональность доступна через пакет Microsoft.Extensions.Configuration.Binder.

Ответ 2

Лучший способ создания экземпляров классов, зависящих от других служб, - это использовать перегрузку Add XXX, которая предоставляет вам IServiceProvider. Таким образом, вам не нужно создавать экземпляр промежуточного поставщика услуг.

В следующих примерах показано, как можно использовать эту перегрузку в методах AddSingleton/AddTransient.

services.AddSingleton(serviceProvider =>
{
    var options = serviceProvider.GetService<IOptions<AppSettings>>();
    var foo = new Foo(options);
    return foo ;
});


services.AddTransient(serviceProvider =>
{
    var options = serviceProvider.GetService<IOptions<AppSettings>>();
    var bar = new Bar(options);
    return bar;
});

Ответ 3

Вы ищете что-то вроде следующего? Вы можете посмотреть мои комментарии в коде:

// this call would new-up `AppSettings` type
services.Configure<AppSettings>(appSettings =>
{
    // bind the newed-up type with the data from the configuration section
    ConfigurationBinder.Bind(appSettings, Configuration.GetConfigurationSection(nameof(AppSettings)));

    // modify these settings if you want to
});

// your updated app settings should be available through DI now