Конфигурация основного доступа 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".