Доступ к конфигурации без инъекции зависимостей

Мне было интересно, есть ли способ получить доступ к Конфигурации (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");

Так что теперь мы можем передавать динамический ключ.