Конфигурация основного доступа ASP.NET из статического класса

Я хочу простой статический класс, который обращается к объекту конфигурации. Вся информация о конфигурации уже считана из файла appsettings.json в классе Startup. Мне просто нужен простой способ получить к нему доступ. Это возможно?

namespace MyNamespace
{
    public static class Config
    {
        public string Username => Configuration["Username"];
        public string Password => Configuration["Password"];
    }
}

В другом месте в приложении:

string username = Config.Username;
string password = Config.Password;

Ответы

Ответ 1

Немного более короткая версия, основанная на том же принципе, что и выше...

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
    StaticConfig = configuration;
}

public static IConfiguration StaticConfig { get; private set; }

Чтобы использовать в другом статическом классе:

string connString = Startup.StaticConfig.GetConnectionString("DefaultConnection");

Ответ 2

Я согласен с mcbowes, это в документации, но первый пример больше похож на то, что вам нужно... want:

public class Program
{
    public static IConfigurationRoot Configuration { get; set; }
    public static void Main(string[] args = null)
    {
        var builder = new ConfigurationBuilder()
             .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json");

        Configuration = builder.Build();

        Console.WriteLine($"option1 = {Configuration["option1"]}");

        // Edit:
        IServiceCollection services = new ServiceCollection();
        services.AddOptions();
        services.Configure<HelloWorldOptions>(_configuration.GetSection("HelloWorld"));
        // And so on...
    }
}

Ответ 3

Старайтесь избегать использования статического класса и использовать DI

namespace MyNamespace {

  public interface IConfig {
    string Username { get; }
    string Password { get; }
  }


  public class Config : IConfig {
    public Config(IConfiguration configuration) {
      _configuration = configuration;
    }
    readonly IConfiguration _configuration;
    public string Username => _configuration["Username"];
    public string Password => _configuration["Password"];
  }


}

Настройка DI в классе StartUp

public class Startup {
  public void ConfigureServices(IServiceCollection services) {
    //...
    services.AddTransient<IConfig, Config>(); 
    ...
  }
}

И использовать это так

  public class TestUsage {
    public TestUsage(IConfig config) {
      _config = config;
    }
    readonly IConfig _config;
    public string Username => _config.Username;
    public string Password => _config.Password;
  }

Ответ 4

После долгих исследований это работает (в ASPNetCore 2.2) для доступа к конфигурации appsettings.json из статического класса, но по какой-то причине appsettings.development.json больше не загружается должным образом, но это может быть что-то еще в моем проекте. ReloadOnChange работает. В качестве бонуса он также имеет IHostingEnvironment и IHttpContextAccessor. Хотя это работает, я недавно решил вернуться к более подходу DI, чтобы следовать смене парадигмы, как уже упоминали другие.

Итак, вот один из многих способов получить доступ к некоторым элементам DI (включая конфигурацию) в статическом классе:

AppServicesHelper.cs:

public static class AppServicesHelper
{
        static IServiceProvider services = null;

        /// <summary>
        /// Provides static access to the framework services provider
        /// </summary>
        public static IServiceProvider Services
        {
            get { return services; }
            set
            {
                if (services != null)
                {
                    throw new Exception("Can't set once a value has already been set.");
                }
                services = value;
            }
        }

        /// <summary>
        /// Provides static access to the current HttpContext
        /// </summary>
        public static HttpContext HttpContext_Current
        {
            get
            {
                IHttpContextAccessor httpContextAccessor = services.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
                return httpContextAccessor?.HttpContext;
            }
        }

        public static IHostingEnvironment HostingEnvironment
        {
            get
            {
                return services.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment;
            }
        }

        /// <summary>
        /// Configuration settings from appsetting.json.
        /// </summary>
        public static MyAppSettings Config
        {
            get
            {
                //This works to get file changes.
                var s = services.GetService(typeof(IOptionsMonitor<MyAppSettings>)) as IOptionsMonitor<MyAppSettings>;
                MyAppSettings config = s.CurrentValue;

                return config;
            }
        }
    }
}

Startup.cs:

public Startup(IHostingEnvironment env)
{
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
 }

 public void ConfigureServices(IServiceCollection services)
 {
//...

        services.AddHttpContextAccessor();//For HttpContext.

        // Register the IOptions object
        services.Configure<MyAppSettings>(Configuration.GetSection(nameof(MyAppSettings)));

        //Explicitly register the settings object by delegating to the IOptions object so that it can be accessed globally via AppServicesHelper.
        services.AddSingleton(resolver => resolver.GetRequiredService<IOptionsMonitor<MyAppSettings>>().CurrentValue);
 }

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
   AppServicesHelper.Services = app.ApplicationServices;
//...
}

контроллер:

public class MyController: Controller
{
   public MyController()
   {
   }

   public MyAppSettings Config => AppServicesHelper.Config;

   public async Task<IActionResult> doSomething()
   {
            testModel tm = await myService.GetModel(Config.Setting_1);
            return View(tm);
   }
}

Другая библиотека классов:

public static class MyLibraryClass
{
     public static string GetMySetting_ => AppServicesHelper.Config.Setting_1; 
     public static bool IsDev => AppServicesHelper.HostingEnvironment.IsDevelopment();
}

MyAppSettings.cs - это любой класс, который отображается в раздел MyAppSettings в appsettings.json:

public class MyAppSettings
{
    public string Setting_1 {get;set;}
}

appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "MyAppSettings": {
      "Setting_1": "something"
   }
 }

Ответ 5

Я нашел это полезным для меня:

public class Startup{

    public IConfiguration Configuration { get; }

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();

        BuildAppSettingsProvider();
    }
    // ...
}

Итерации по всем статическим свойствам вашего статического класса AppSettings, устанавливая их значения из appSettings.json

public static class AppSettings
{
    public static string AppSetting1 { get; set; }
    // ...
}

private void BuildAppSettingsProvider()
{
    var type = typeof(AppSettings);
    var properties = type.GetProperties();
    foreach (var property in properties)
    {
        property.SetValue(null, Configuration[property.Name]);
    }
}

Таким образом, вы можете получить доступ к настройкам приложения как таковым:

AppSettings.AppSetting1;

Ответ 6

Это уже было сказано, но я собираюсь сказать это.

Статические классы не являются лучшей практикой объектно-ориентированного программирования. Я думаю, что по этой причине .Net Core предоставляет нам способ получения значений с помощью Dependency Inject. Это то, что я заметил из своих исследований, но я также немного размышляю. Как разработчики, мы должны следовать этой смене парадигмы, чтобы хорошо использовать .Net Core.

Шаблон параметров является хорошей альтернативой статической конфигурации. В вашем случае это будет выглядеть так:

appsettings.json

{
  "Username": "MyUsername",
  "Password": "Password1234"
}

SystemUser.cs

public class SystemUser 
{
  public string Username { get; set; } = "";
  public string Password { get; set; } = "";
}

Startup.cs

services.Configure<SystemUser>(Configuration);

И чтобы использовать класс SystemUser, мы делаем следующее.

TestController.cs

public class TestController : Controller 
{
  private readonly SystemUser systemUser;

  public TestController(IOptionsMonitor<SystemUser> systemUserOptions)
  {
    this.systemUser = systemUserOptions.CurrentValue;
  }

  public void SomeMethod() 
  {
    var username = this.systemUser.Username; // "MyUsername"
    var password = this.systemUser.Password; // "Password1234"
  }
}

Хотя мы не используем статический класс, я думаю, что это лучшая альтернатива, которая соответствует вашим потребностям. В противном случае вам, возможно, придется использовать статическое свойство внутри класса Startup, что является пугающим решением imo.

Ответ 7

Вот способ получить значения конфигурации со страницы NET.Core без необходимости ссылаться на них статически, но при этом иметь возможность передавать их другим статическим функциям, вызываемым из нестатического класса.

В верхней части вашего нестатического класса добавьте это:

private readonly IConfiguration _configuration;

Затем в функции конструктора IConfiguration configuration существующую конфигурацию в качестве входных данных для функции: IConfiguration configuration

Затем назначьте конфигурацию вашей переменной только для чтения внутри функции конструктора: _configuration = configuration;

Вот пример того, как это должно выглядеть:

public class IndexModel : PageModel
{
    private readonly IConfiguration _configuration;

    public IndexModel(IConfiguration configuration)
    {
        _configuration = configuration;
    }
}

После этого вы можете ссылаться на конфигурацию в любой функции в классе, ссылаясь на _configuration, и даже можете затем передать ее другим статическим функциям, которые вы вызываете из других классов:

public async Task OnGetAsync()
{
    AnotherClass.SomeFunction(_configuration);
}

Затем в вызываемом статическом классе я могу использовать значения конфигурации:

public static string SomeFunction(IConfiguration configuration)
{
    string SomeValue = configuration.GetSection("SomeSectionOfConfig")["SomeValue"];
}

У меня есть класс, который вызывает некоторые хранимые процедуры для просмотра и изменения данных и передает значения параметров из appsettings.json, используя этот подход.

Ответ 8

Если вы используете переменные среды в качестве своей конфигурации, вы можете получить доступ к переменной среды напрямую, а не через объект конфигурации.

using System;

namespace My.Example
{
    public static class GetPaths
    {
        private static readonly string MyPATH = 
            Environment.GetEnvironmentVariable("PATH");

        private static readonly string MySpecialPath =
            Environment.GetEnvironmentVariable("PREFIX_SpecialPath");
        ...
    }
}

Ответ 9

Лично мне нравится метод, используемый в этой ссылке

По сути, это просто добавление статического поля в ваш класс параметров.

 public class WeblogConfiguration
 {
    public static WeblogConfiguration Current;

    public WeblogConfiguration()
    {
        Current = this;
    }
} 

Тогда в любом статическом классе вы можете сделать:

WeblogConfiguration.Current

Простой и очень прямой

Ответ 10

Я думаю, что вы могли бы использовать функцию расширения, что-то вроде этого

public static string ConfigToSomeThing(this IConfiguration config, int value)
        {
            return config[value.ToString()] ?? "";
        }

Тогда в любом месте, просто инъекция IConfiguration и использование метода расширения

_systemConfiguration.ConfigToSomeThing(123);

Ответ 11

Рассмотрите возможность использования инструкции здесь для конфигурации ASP.NET Core.

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

_config.UserName

В Startup - ConfigureServices:

services.Configure<Config>(Configuration.GetSections("General"));

Затем просто введите свой объект туда, где вам нужно:

IOptions<Config> config

Ответ 12

IConfiguration является Injectable в любом месте проекта. Но в случае статического класса параметр, который я использую и, возможно, подходит только... var Configuration = new ConfigurationBuilder().AddUserSecrets<Startup>().Build(); И вы можете добавить требуемый раздел, например, в этом блоке кода выше, я добавил "UserSecrets".