Получение IConfiguration из ServiceCollection
Я пишу свой собственный метод расширения для ServiceCollection
для зарегистрированных типов моего модуля, и мне нужно получить доступ к IConfiguration
экземпляр из коллекции, чтобы зарегистрировать мои параметры.
Метод расширения
public static IServiceCollection AddApi(this IServiceCollection services)
{
// Get configuration from collection
var configuration = (IConfiguration) services.FirstOrDefault(p => p.ServiceType == typeof(IConfiguration)).ImplementationInstance;
services.Configure<DatabaseOptions>(configuration.GetSection("Database"));
}
Это правильный способ получить IConfiguration
экземпляр из коллекции или есть более элегантное решение? Я не хочу добавлять экземпляр IConfiguration в качестве параметра к методу.
4 ответа
В соответствии с комментариями я изменил свой метод расширения на следующий, так что именно разработчик приложения должен предоставить раздел конфигурации для моих опций.
public static IServiceCollection AddApi(this IServiceCollection services, IConfiguration databaseConfiguration)
{
services.Configure<DatabaseOptions>(databaseConfiguration);
}
из класса StartUp, вызов выглядит
public void ConfigureServices(IServiceCollection services)
{
services.AddApi(Configuration.GetSection("Database"));
services.AddMvc();
}
Решение использовать его таким образом в основном из этих комментариев. Этот способ может быть более уместным при разработке компонентов, которые используются многими разработчиками, чем для внутреннего компонента, который вы используете в своем приложении.
Имхо, это плохой дизайн для доступа к IConfiguration из любого места, кроме как внутри корня композиции (класс запуска для ядра ASP.NET), так как это подразумевает, что файл конфигурации должен иметь определенную структуру, которую вообще нельзя изменить. Вместо этого я написал бы метод расширения для настройки классов конфигурации внутри корня композиции и передачи объекта IConfiguration, аналогично тому, как.Configure(Configuration.GetSection("MyLibConfi g"). Таким образом, разработчик, который создает свое приложение из ваших компонентов может решить, где разместить его в appsettings.json
Или как бы вы решили конфликты, когда две библиотеки напрямую ссылаются на IConfiguration и имеют один и тот же раздел в конфигурации? т.е. JsonSettings, но имеют совершенно другую структуру? Это может быть решено только путем предоставления разработчику, который его составляет, выбора и передачи имени раздела в метод расширения, который устанавливает параметры через.Configure.
Получить IConfiguration
от IServiceCollection
почему бы просто не разрешить зависимость?:
IConfiguration configuration = services.BuildServiceProvider().GetService<IConfiguration>();
Я создал свой собственный тип "коллекции услуг", который обернул IServiceCollection
а также IConfiguration
и все мои модули используют этот тип для регистрации своих услуг. Например:
public interface IMyServiceCollection
{
public IServiceCollection Services { get; set; }
public IConfiguration Configuration { get; set; }
}
public static void AddFooModule(this IMyServiceCollection myServices)
{
var services = myServices.Services;
var config = myServices.Configuration;
}
Затем вы должны создать метод расширения с экземпляром конфигурации в качестве параметра, который создает реализацию для IMyServiceCollection
, такие как:
public static IMyServiceCollection CreateServiceCollection(this IServiceCollection services, IConfiguration config)
{
return new MyServiceCollection
{
Services = services,
Configuration = config
};
}
Обратите внимание, что мы используем это в модульной структуре. Для простых приложений это излишне.
Я думаю, что ваше решение тоже хорошо. Но если вам нужен доступ к IConfiguration
Например, часто вы можете найти его поиск в коллекции сервисов снова и снова немного утомительно.
Документы говорят , что вы должны потребовать от пользователя предоставить вам соответствующую IConfiguration:
public static IServiceCollection AddApi(this IServiceCollection services, IConfiguration configSection)
{
services.Configure<DatabaseOptions>(configSection);
// ...
return services;
}
Вам понадобится пакетMicrosoft.Extensions.Options.ConfigurationExtensions
чтобы это работало.