Utilisation d’IConfiguration dans la bibliothèque de classes C #

Je construis une bibliothèque de classes en utilisant C # et Core .NET. J’essaie d’utiliser la configuration à partir d’un fichier config.json . Voici le contenu de ce fichier:

config.json

 { "emailAddress":"[email protected]" } 

Dans le but d’utiliser config.json pour ma configuration, je fais référence à Microsoft.Framework.ConfigurationModel.Json dans mon fichier project.json . Dans mon code, j’ai les éléments suivants:

MyClass.cs

 using Microsoft.Framework.ConfigurationModel; public class MyClass { public ssortingng GetEmailAddress() { // return ConfigurationManager.AppSettings["emailAddress"]; This is the approach I had been using since .NET 2.0 return ?; // What goes here? } } 

Depuis .NET 2.0, j’utilisais ConfigurationManager.AppSettings["emailAddress"] . Cependant, j’essaie maintenant d’apprendre à le faire de la nouvelle manière via IConfiguration . Mon problème est, ceci est une bibliothèque de classe. Pour cette raison, je ne sais pas comment, ni où, ni quand le fichier de configuration est chargé. En .NET traditionnel, je devais simplement nommer un fichier web.config pour les projets ASP.NET et app.config pour d’autres projets. Maintenant, je ne suis pas sûr. J’ai à la fois un projet ASP.NET MVC 6 et un projet XUnit. J’essaie donc de comprendre comment utiliser config.json dans ces deux scénarios.

Je vous remercie!

Jamais utilisé, mais une recherche rapide m’a conduit à ceci …

 var configuration = new Configuration(); configuration.AddJsonFile(“config.json”); var emailAddress = configuration.Get("emailAddress"); 

Peut-être que vous pourriez essayer ça.

Les bibliothèques de classes IMO doivent être agnostiques aux données de parameters d’application. En règle générale, le consommateur de bibliothèque est celui qui est concerné par ces détails. Oui, ce n’est pas toujours vrai (par exemple, si vous avez une classe qui effectue le cryptage / décryptage RSA, vous souhaiterez peut-être qu’une configuration privée permette la génération / le stockage de la clé privée), mais dans la plupart des cas, c’est vrai.

Donc, en général, essayez de garder les parameters de l’application en dehors de la bibliothèque de classes et demandez au consommateur de fournir ces données. Dans votre commentaire, vous mentionnez une chaîne de connexion à une firebase database. C’est un exemple parfait de données à conserver en dehors d’une bibliothèque de classes. La bibliothèque ne devrait pas se soucier de la firebase database à laquelle elle appelle pour lire, mais simplement du fait qu’elle doit en lire une. Exemple ci-dessous (je m’excuse s’il y a des erreurs car j’écris ceci à la volée de mémoire):

Bibliothèque

Classe de bibliothèque qui utilise une chaîne de connexion

 public class LibraryClassThatNeedsConnectionSsortingng { private ssortingng connectionSsortingng; public LibraryClassThatNeedsConnectionSsortingng(ssortingng connectionSsortingng) { this.connectionSsortingng = connectionSsortingng; } public ssortingng ReadTheDatabase(int somePrimaryKeyIdToRead) { var result = ssortingng.Empty; // Read your database and set result return result; } } 

Application

appsettings.json

 { "DatabaseSettings": { "ConnectionSsortingng": "MySuperCoolConnectionSsortingngWouldGoHere" } } 

DatabaseSettings.cs

 public class DatabaseSettings { public ssortingng ConnectionSsortingng { get; set; } } 

Startup.cs

 public class Startup { public Startup(IHostingEnvironment env) { Configuration = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables() .Build(); } public IConfigurationRoot Configuration { get; } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { // Setup logging // Configure app } public void ConfigureServices(IServiceCollection services) { // Configure services services.Configure(Configuration.GetSection("DatabaseSettings")); services.AddOptions(); // Register our class that reads the DB into the DI framework services.AddTransient(); } } 

Classe qui utilise la classe library pour lire la firebase database

 public interface IInterfaceForClass { ssortingng ReadDatabaseUsingClassLibrary(int somePrimaryKeyIdToRead); } public class ClassThatNeedsToReadDatabaseUsingLibrary : IInterfaceForClass { private DatabaseSettings dbSettings; private LibraryClassThatNeedsConnectionSsortingng libraryClassThatNeedsConnectionSsortingng; public ClassThatNeedsToReadDatabaseUsingLibrary(IOptions dbOptions) { this.dbSettings = dbOptions.Value; this.libraryClassThatNeedsConnectionSsortingng = new LibraryClassThatNeedsConnectionSsortingng(this.dbSettings.ConnectionSsortingng); } public ssortingng ReadDatabaseUsingClassLibrary(int somePrimaryKeyIdToRead) { return this.libraryClassThatNeedsConnectionSsortingng.ReadTheDatabase(somePrimaryKeyIdToRead); } } 

Une classe de contrôleur qui gère les éléments d’interface utilisateur à lire dans la firebase database

 public class SomeController : Controller { private readonly classThatReadsFromDb; public SomeController(IInterfaceForClass classThatReadsFromDb) { this.classThatReadsFromDb = classThatReadsFromDb; } // Controller methods } 

TL; DR

Essayez d’éviter d’utiliser les parameters d’application dans une bibliothèque de classes. Au lieu de cela, demandez à votre bibliothèque de classes d’être agnostique vis-à-vis de tels parameters et laissez le consommateur le transmettre.

Modifier:

J’ai ajouté l’dependency injection dans une classe de contrôleur pour illustrer l’utilisation de l’dependency injection pour créer la classe qui lit à partir de la firebase database. Cela permet au système DI de résoudre les dépendances nécessaires (par exemple, les options de firebase database).

C’est une façon de le faire (et la meilleure façon). Une autre méthode consiste à injecter les IOptions dans le contrôleur et à créer manuellement la classe qui lit dans la firebase database et à transmettre les options (non, ce n’est pas une bonne pratique, DI est une meilleure solution).

Dans votre fichier .csproj , ajoutez d’abord une cible correspondant au processus de construction. Pour plus d’options, voir le lien correspondant si ce qui suit ne correspond pas à vos besoins, comme la publication.

    

vous pouvez l’utiliser comme suit

 using Microsoft.Framework.ConfigurationModel; using Microsoft.Extensions.Configuration; using System; public class MyClass { public ssortingng GetEmailAddress() { //For example purpose only, try to move this to a right place like configuration manager class ssortingng basePath= System.AppContext.BaseDirectory; IConfigurationRoot configuration= new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("config.json") .Build(); return configuration.Get("emailAddress"); } } 

Je ne sais pas si cela fonctionne dans une bibliothèque core.net, mais dans mon application mvc6, je l’utilise de cette façon:

 public class Startup { public static IConfigurationRoot Configuration; public Startup(IApplicationEnvironment appEnv) { var builder = new ConfigurationBuilder() .SetBasePath(appEnv.ApplicationBasePath) .AddJsonFile("config.json") .AddEnvironmentVariables(); Configuration = builder.Build(); } } 

alors si j’ai besoin d’appeler l’info dans le config.jason dans l’application, je le fais: c’est-à-dire dans une méthode de contrôleur:

 var email = Startup.Configuration["AppSettings:SiteEmailAddress"]; 

sql ssortingng dans ma classe WonderContext:

 var connSsortingng = Startup.Configuration["AppSettings:WonderContextConnection"];