Комментарии 24
Вы как-то лихо смешиваете ASP.NET Core и .NET Core в статье.
Nuget пакеты с инфраструктурой конфигурации ни как не зависят от ASP.NET Core и таргетятся на .NETStandard 2.0. Таким образом их можно использовать не только в ASP.NET Core приложениях, но и в любых .NET Core и .NET Framework приложениях.
Слегка смущает лишь то, что весь код лежит в репозитории ASP.NET Core.
Вы как-то лихо смешиваете ASP.NET Core и .NET Core в статье.
Действительно лихо. Причина в том, что как вы уже писали пакет Microsoft.Extensions не зависит от ASP.NET Core. Но проблемы, которые я описывал касаются использования конфигурации в ASP.NET Core. В приложениях .NET Core и .NET Framework они могут и не возникнуть, потому что у нас нет волшебного метода CreateDefaultBuilder, который скрывает за кулисами всю рутинную работу.
Данная статья затрагивает лишь основы. Помимо основ нам доступны IOptions, сценарии пост-конфигурации, валидация настроек и многое другое. Но это уже другая история.
Самая интресная история.
В общем, про IRL-использование и хорошии практики, а не пересказ docs.microsoft.com/ru-ru/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.2
Может быть вы знаете по какой причине разработчики ASP.NET Core ввели конфигурацию на основе переменных окружения? Насколько я знаю такой тип источника конфигурации не пользовался популярностью в .NET Framework? Вполне возможно что я пропустил что-то важное или же очевидное но никак не могу понять этот момент
Опять же передавать всякие секреты в различных окружениях тоже можно.
Жалко только обязательных параметров без извращение с ioption не сделать никак…
И это то, что я сказал во второй части предложения.
Как по мне, так использование опций с DataAnnotation-атрибутами это самое лучшее решение. За некоторыми нюансами, что ошибка валидации будет происходит где-то в рантайме, только при запросе опций через DI. Но это обещают исправить в .NET Core 3.0
Если нет желания использовать опции, можно реализовать что-то типа IStartupFilter и там проверять конфигурацию. Но мне кажется это то еще извращение.
Я иногда вообще не хочу использовать DI. Не говоря про то, что у меня консольное приложение, без MVC. Зачем мне туда тащить эти IOption непонятно.
В итоге я отказался от всей этой конфигурации вообще и просто паршу JSON руками:
public class Config
{
private readonly JObject _json;
public Config(string file)
{
_json = JObject.Parse(File.ReadAllText(file));
}
public T GetSection<T>(string sectionName = null) where T : class
{
if (sectionName == null)
{
sectionName = typeof(T).Name;
}
return _json[sectionName]?.ToObject<T>() ??
throw new InvalidOperationException($"Cannot find section {sectionName}");
}
}
public class EthereumBaseSettings
{
[JsonProperty(Required = Required.Always)]
public string AccountAddress { get; }
[JsonProperty(Required = Required.Always)]
public string PrivateKey { get; }
[JsonProperty(Required = Required.Always)]
public string AccountPassword { get; }
[JsonProperty(Required = Required.Always)]
public string RootContractAddress { get; }
[JsonProperty(Required = Required.Always)]
public string ParityConnectionString { get; }
public EthereumBaseSettings(string accountAddress,
string privateKey,
string accountPassword,
string rootContractAddress,
string parityConnectionString)
{
AccountAddress = accountAddress;
PrivateKey = privateKey;
AccountPassword = accountPassword;
RootContractAddress = rootContractAddress;
ParityConnectionString = parityConnectionString;
}
}
И я точно знаю, что мне не надо пользоваться обязательным DI от майкрософта чтобы получить валидный объект, и не иметь инфраструктурной обвязки от них же во всех сервисных классах. Да, пришлось отказаться от мержа нескольких конфигов, но как показала практика не так уж оно и нужно.
Если в разных источниках конфигурации присутствуют одинаковые ключи (сравнение идет без учета регистра), то используется значение, которое было добавлено последним.
Это не всегда так. Для массивов будет просто добавление элемента в массив.
Да, вы отчасти правы. Для массивов, элементы с одинаковыми индексами будут заменены, с уникальными индексами будут добавлены. Добавлю в статью.
На сколько помню ничего не заменяется. Просто добавляется. Например в случае массива в appsettings.json и appsettings.Development.json
В зависимости от переменной окружения выбирается тот или иной источник конфигурации.
Получается, что при сборке бинарников приложения там будут файлы конфигураций для всех environment и нужно как-то вручную удалять лишние?
Есть ли способы комбинирования настроек через переменные окружения и через файлы?
Например чтобы при запуске локально настройки брались из файла, а при запуске в тестовом окружении их переменных окружения?
Получается, что при сборке бинарников приложения там будут файлы конфигураций для всех environment и нужно как-то вручную удалять лишние?
Да, действительно при публикации приложения, все файлы .json попадают в выходную папку, не смотря на то, что в их свойствах стоит опция Do not copy. Чтобы решить эту проблему можно добавить в .csproj MSBuild conditional constructs с , но это не выглядит прямым решением проблемы.
Есть ли способы комбинирования настроек через переменные окружения и через файлы?
Есть. Вспомним пример:
{
"Settings": {
"Key": "I am options"
}
}
Будет приведен к плоскому виду:
Settings:Key = I am options
Если создать переменную окружения с ключом Settings__Key, она заменит настройку из файла. Подробнее здесь.
Как работает конфигурация в .NET Core