146 votes

ASP.NET Core - accédez à la configuration à partir d'une classe statique

Je veux une classe statique simple qui accède à l'objet de configuration. Toutes les informations de configuration sont déjà extraites du fichier appsettings.json de la classe Startup. J'ai juste besoin d'un moyen facile d'y accéder. Est-ce possible?

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

Partout ailleurs dans l'application:

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

112voto

DeanC Points 191

Une version légèrement plus courte basée sur le même principe que ci-dessus ...

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

public static IConfiguration StaticConfig { get; private set; }
 

Pour utiliser dans une autre classe statique:

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

18voto

Soenhay Points 1455

Après beaucoup de recherches, cela fonctionne (en ASPNetCore 2.2) pour l'accès à la appsettings.json config à partir d'une classe statique, mais pour une raison quelconque appsettings.développement.json ne charge plus correctement, mais il pourrait être quelque chose d'autre dans mon projet de gâcher ça. Le reloadOnChange fonctionne. En bonus, il a également IHostingEnvironment et IHttpContextAccessor. Bien que cela fonctionne, j'ai récemment décidé de revenir à une plus DI approche à suivre le changement de paradigme comme d'autres l'ont mentionné.

Donc, ici, est l'une des nombreuses façons d'accéder à certaines DI trucs (y compris la configuration) dans une classe statique:

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

De démarrage.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;
//...
}

Contrôleur:

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

Une autre classe de la bibliothèque:

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

MyAppSettings.cs est toute la classe qui correspond à un MyAppSettings section appsettings.json:

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

appsettings.json:

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

13voto

Tubbe Points 423

Je suis d'accord avec mcbowes, c'est dans la documentation , mais le premier exemple ressemble plus à ce dont vous avez besoin ... voulez:

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

8voto

tb-mtg Points 86

Essayez d'éviter d'utiliser une classe statique et utilisez 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"];
  }


}
 

Le DI d'installation dans la classe StartUp

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

Et l'utiliser comme ça

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

5voto

christo8989 Points 2303

Cela a déjà été dit mais je vais le dire.

Les classes statiques ne sont pas une meilleure pratique de la Programmation Orientée Objet. Je pense que pour cette raison, .Net de Base nous fournit un moyen d'obtenir des valeurs par le biais de la Dépendance de l'injection. C'est ce que j'ai remarqué au cours de ma recherche, mais je suis aussi de spéculer un peu. En tant que développeurs, nous devons suivre ce changement de paradigme pour l'utiliser .Net de Base bien.

Les Options de Modèle est une bonne alternative à la statique de la config. Dans votre cas, il va ressembler à ceci:

appsettings.json

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

SystemUser.cs

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

De démarrage.cs

services.Configure<SystemUser>(Configuration);

Et pour utiliser le SystemUser classe, nous faisons la suite.

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

Même si nous ne sommes pas à l'aide d'une classe statique, je pense que c'est la meilleure alternative qui s'adapte à vos besoins. Sinon, vous pourriez avoir à utiliser une propriété statique à l'intérieur du Démarrage de la classe qui est effrayant une solution de l'omi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X