NET 核心ーー静态类的访问配置

我想要一个访问 Configuration 对象的简单静态类。所有的配置信息都已经从 Startup 类中的 appsetings.json 文件读入。我只是需要一个简单的方法进入它。这可能吗?

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

Anywhere else in the app:

string username = Config.Username;
string password = Config.Password;
105312 次浏览

Consider using the instructions 给你 for ASP.NET Core Configuration.

您可以创建一个类来存储配置设置,然后访问这些值,如下所示:

_config.UserName

在启动-配置服务:

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

然后在需要的任何地方注入对象:

IOptions<Config> config

我同意 McBowes 的观点,它在 医生中,但是第一个例子看起来更像是你需要的... ... 想要的:

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...
}
}

IConfiguration在项目的任何地方都是可注射的。但是在静态类的情况下,我正在使用的选项,也许只是方法..。

var Configuration = new ConfigurationBuilder()
.AddUserSecrets<Startup>()
.Build();

并且,您可以添加所需的部分,比如在上面的代码块中,我添加了“ UserSecret”。

尽量避免使用静态类并使用 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"];
}




}

StartUp 类中的安装 DI

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;
}

一个稍微简短的版本,基于同样的原则,如上所述..。

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


public static IConfiguration StaticConfig { get; private set; }

在另一个静态类中使用:

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

这话已经说过了,但我还是要说。

我相信。NetCore 希望开发人员通过 DependencyInject 获得价值。这是我在研究中注意到的,但我也有一些推测。作为开发人员,为了使用。网络核心运行良好。

Options Pattern是静态配置的一个很好的替代品:

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。

经过大量研究,这种方法(在 ASPNetCore 2.2中)可以从静态类访问 appsetings.json 配置,但出于某种原因 appsetings.development.json 不再正确加载,但可能是我的项目中的其他东西搞砸了。ReloadOnChange 可以工作。另外,它还有 IHostingEnvironment 和 IHttpContextAccessor。虽然这是有效的,但是我最近决定切换回更多的依赖注入方法,以遵循其他人提到的范式转变。

因此,这里是在静态类中访问一些 DI 内容(包括配置)的许多方法之一:

Appserviceshelper.cs :

public static class AppServicesHelper
{
static IServiceProvider services = null;


/// <summary>
/// Provides static access to the framework's 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 是映射到 appsetings.json 中的 MyAppSettings 部分的任何类:

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

Appsettings.json:

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

下面是一种从 NET.Core 页面获取配置值的方法,它不需要静态地引用这些值,但是仍然可以将它们传递给从非静态类调用的其他静态函数。

在非静态类的顶部添加以下内容:

private readonly IConfiguration _configuration;

Then in the constructor function bring in the existing configuration as input to the function: 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"];
}


我有一个类,它调用一些存储过程来查看和修改数据,并使用这种方法从 appsetings.json 传递参数值。

如果您使用环境变量作为您的配置 ,您可以直接访问环境变量,而不是通过配置对象。

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");
...
}
}

就个人而言,我喜欢这个 链接中使用的方法

本质上,它只是向选项类添加一个静态字段。

 public class WeblogConfiguration
{
public static WeblogConfiguration Current;


public WeblogConfiguration()
{
Current = this;
}
}

Then in any static class you can do:

WeblogConfiguration.Current

简单明了

我认为你可以使用扩展函数,类似这样的东西

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

然后在任何地方,只需注入 IConfiguration 并使用扩展方法

_systemConfiguration.ConfigToSomeThing(123);

您可以使用 西格尔顿模式从任何地方访问您的配置

    public class ConnectionStrings
{
private ConnectionStrings()
{
}
// property with getter only will not work.
public static ConnectionStrings Instance { get; protected set; } = new ConnectionStrings();


public string DatabaseConnection { get; set; }
}

还有你的创业课

    public class Startup
{
private readonly IConfiguration configuration;


public Startup(IConfiguration configuration)
{
this.configuration = configuration;
configuration.GetSection("ConnectionStrings").Bind(ConnectionStrings.Instance);
}


public void ConfigureServices(IServiceCollection services)
{
}


public void Configure(IApplicationBuilder app)
{
}
}

我刚刚创建了下面的类:


/// <summary>
///
/// </summary>
public static class ConfigurationManager
{
/// <summary>
///
/// </summary>
public sealed class ConfigurationManagerAppSettings
{
/// <summary>
///
/// </summary>
internal ConfigurationManagerAppSettings() { }


/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string this[string key] => (TheConfiguration ?? throw new Exception("Set ConfigurationManager.TheConfiguration in Startup.cs")).GetSection($"AppSettings:{key}").Value;
}


/// <summary>
///
/// </summary>
public static IConfiguration? TheConfiguration { get; set; }


/// <summary>
///
/// </summary>
public static readonly ConfigurationManagerAppSettings AppSettings = new ConfigurationManagerAppSettings();
}

下面是我的代码:

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


public IConfiguration Configuration { get; }


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
ConfigurationManager.TheConfiguration = Configuration;


  1. create the ConfigurationHelper static class in the service layer, so it can be used in other layers without circular dependency.
public static class ConfigurationHelper
{
public static IConfiguration config;
public static void Initialize(IConfiguration Configuration)
{
config = Configuration;
}
}
  1. 在 Startup 类的 ConfigureServices 方法内初始化 ConfigurationHelper。
ConfigurationHelper.Initialize(Configuration);
  1. 在任何需要包含静态类的地方使用它
e.g: ConfigurationHelper.config.GetSection("AWS:Accesskey").Value;

我也遇到过类似的问题,在阅读了微软的 文件之后,我解决了这个问题:

  1. 创建静态 ApplicationSettings 类
public static class ApplicationSettings
{
public const string User = "UserOptions";


public static UserOptions UserOptions { get; set; } = new UserOptions();


// other options here...
}
  1. 创建选项类
public class UserOptions
{
public string Username { get; set; };


public string Password { get; set; };
}
  1. 在 Program.cs 中初始化 Options 类
ConfigurationManager configuration = builder.Configuration;


configuration.GetSection(ApplicationSettings.User).Bind(ApplicationSettings.UserOptions);
  1. 更新 appsetings.json
{
"UserOptions": {
"Username": "input_your_username_here",
"Password": "input_your_password_here"
}
}
  1. 现在可以在项目中的任何地方调用它
public void MethodA()
{
string username = ApplicationSettings.UserOptions.Username;
string password = ApplicationSettings.UserOptions.Password;
}


public static void MethodB()
{
string username = ApplicationSettings.UserOptions.Username;
string password = ApplicationSettings.UserOptions.Password;
}

希望这能对你有所帮助。

我已经使用过这种方法,它似乎工作得很好。

namespace MyNamespace
{
public static class Config
{
public static IConfiguration Configuration { get; set; }


public string Username => Configuration["Username"];
public string Password => Configuration["Password"];
}
}

在 Startup.cs 构造函数中,使用依赖注入获取配置,然后将其分配给静态类的 public 成员。

public class Startup
{
public Startup(IConfiguration configuration)
{
MyNamespace.Config.Configuration = configuration;
}


// The rest of the startup code...
}