Доступ к конфигурации без инъекции зависимостей
Мне было интересно, есть ли способ получить доступ к Конфигурации (Microsoft.Extensions.Configuration) без использования инъекции зависимостей. Только примеры, которые я вижу, - это инъекция конструктора (с использованием IOptions или непосредственного ввода конфигурации).
Моя дилемма заключается в том, что у меня есть класс утилиты - не служба, которая имеет статические методы, чтобы делать вещи "на лету". В некоторых из этих статических методов я хотел бы получить несколько свойств из appsettings.json динамически. Поскольку это строго класс утилиты, я не хочу, чтобы этот класс вводился в каждый класс, который должен использовать метод или два из утилиты.
Любые идеи о том, как получить доступ к свойствам appsettings.json без какой-либо инъекции зависимостей.
FYI: использование С# и .net core 1.1
Ответы
Ответ 1
Ничего себе, что много комментариев, почему люди не отвечают на вопрос, а не говорят кому-то, что они не хотят делать то, что они явно делают. В любом случае, мы надеемся, что это сохранит оба лагеря.
Если вы возьмете стандартный класс AppSettings с одним открытым конструктором, который принимает конфигурацию IConfiguration, которая может использоваться для заполнения всех свойств AppSettings, это сохраняет возможность инъекции зависимостей.
Если в конце конструктора мы устанавливаем статическое свойство "Текущий", указывающее на текущий экземпляр AppSettings, это позволит нам получить доступ к настройкам с этой точки через статическое свойство без необходимости дальнейшей инъекции.
Если теперь мы создадим статический метод "GetCurrentSettings" по умолчанию, чтобы получить настройки из json файла, это можно использовать в качестве экземпляра по умолчанию, так что если "Current" вызывается и имеет значение null, мы просто уходим и заполнить настройки из файла. Вот пример того, что я имею в виду...
public class AppSettings
{
private static AppSettings _appSettings;
public string AppConnection { get; set; }
public AppSettings(IConfiguration config)
{
this.AppConnection = config.GetValue<string>("AppConnection");
// Now set Current
_appSettings = this;
}
public static AppSettings Current
{
get
{
if(_appSettings == null)
{
_appSettings = GetCurrentSettings();
}
return _appSettings;
}
}
public static AppSettings GetCurrentSettings()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
IConfigurationRoot configuration = builder.Build();
var settings = new AppSettings(configuration.GetSection("AppSettings"));
return settings;
}
}
Итак, из этого вы могли бы позвонить в любом месте кода AppSettings.Current.AppConnection
Если он был создан с использованием DI, то была бы выбрана версия с впрыском, иначе версия по умолчанию будет взята из файла appsettings.json. Я сомневаюсь, что он удовлетворяет всех, и я не уверен, что объяснил это очень хорошо, но, надеюсь, это имеет смысл.
Ответ 2
У меня есть класс утилиты - не служба, у которой есть статические методы
Это действительно суть вашей проблемы. У вас есть статические методы с зависимостями, которые не являются дружественными к DI.
Я бы сказал, что у вас есть хороший кандидат на услугу, которую вы внесли в класс утилиты. В результате этого вы лишили себя возможности правильно использовать DI. Либо сделайте класс классом экземпляра, либо извлеките применимую функциональность в службу, и у вас появится возможность вставить вашу зависимость IOptions
.
Вам следует избегать статических классов/методов для всего, что имеет (или может иметь) зависимости.
Ответ 3
Я только что создал свойство config в Startup
static:
public static IConfiguration Configuration { get; set; }
Теперь я могу получить доступ к нему в любом месте приложения только с помощью Startup.Configuration
.
Ответ 4
Я полностью согласен с решением, предложенным @Hoot, но я немного изменил класс. Я изменил класс, потому что мне нужно передать динамический ключ для получения значения для того же..
Класс конфигурации:
public class ConfigHelper
{
private static ConfigHelper _appSettings;
public string appSettingValue { get; set; }
public static string AppSetting(string Key)
{
_appSettings = GetCurrentSettings(Key);
return _appSettings.appSettingValue;
}
public ConfigHelper(IConfiguration config, string Key)
{
this.appSettingValue = config.GetValue<string>(Key);
}
public static ConfigHelper GetCurrentSettings(string Key)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
IConfigurationRoot configuration = builder.Build();
var settings = new ConfigHelper(configuration.GetSection("AppSettings"), Key);
return settings;
}
}
Конфигурация Appsettings.Json:
"AppSettings": {
"WebApplicationUrl": "http://localhost:0000/",
"ServiceUrl": "http://localhost:0000/",
"CommonServiceUrl": "http://localhost:0000/"
}
Пример вызова:
string ServiceUrl = ConfigHelper.AppSetting("ServiceUrl");
Так что теперь мы можем передавать динамический ключ.