Equivalente a “app.config” per una libreria (DLL)

Esiste un equivalente a app.config per le librerie (DLL)? In caso contrario, qual è il modo più semplice per memorizzare le impostazioni di configurazione specifiche di una libreria? Si prega di considerare che la libreria potrebbe essere utilizzata in diverse applicazioni.

Puoi avere un file di configurazione separato, ma dovrai leggerlo “manualmente”, il ConfigurationManager.AppSettings["key"] leggerà solo la configurazione del gruppo in esecuzione.

Supponendo che stai usando Visual Studio come IDE, puoi fare clic con il tasto destro del mouse sul progetto desiderato → Aggiungi → Nuovo elemento → File di configurazione dell’applicazione

Ciò aggiungerà App.config alla cartella del progetto, App.config le impostazioni nella sezione . Se non stai usando Visual Studio e aggiungi il file manualmente, assicurati di dargli un nome simile: DllName.dll.config , altrimenti il ​​codice qui sotto non funzionerà correttamente.

Ora leggere da questo file ha una tale funzione:

 string GetAppSetting(Configuration config, string key) { KeyValueConfigurationElement element = config.AppSettings.Settings[key]; if (element != null) { string value = element.Value; if (!string.IsNullOrEmpty(value)) return value; } return string.Empty; } 

E per usarlo:

 Configuration config = null; string exeConfigPath = this.GetType().Assembly.Location; try { config = ConfigurationManager.OpenExeConfiguration(exeConfigPath); } catch (Exception ex) { //handle errror here.. means DLL has no sattelite configuration file. } if (config != null) { string myValue = GetAppSetting(config, "myKey"); ... } 

Dovrai anche aggiungere un riferimento allo spazio dei nomi System.Configuration per avere la class ConfigurationManager disponibile.

Quando si DllName.dll.config il progetto, oltre alla DLL si avrà DllName.dll.config file DllName.dll.config , che è il file che si deve pubblicare con la DLL stessa.

Quanto sopra è un codice di esempio di base, per coloro che sono interessati a un esempio in scala reale, fare riferimento a questa altra risposta .

Sfortunatamente, puoi avere un solo file app.config per eseguibile, quindi se hai DLL collegate all’applicazione, non possono avere i propri file app.config.

La soluzione è: non è necessario inserire il file App.config nel progetto della libreria di classi.
Metti il ​​file App.config nell’applicazione che fa riferimento alla dll della libreria di classi.

Ad esempio, supponiamo di avere una libreria di classi denominata MyClasses.dll che utilizza il file app.config in questo modo:

 string connect = ConfigurationSettings.AppSettings["MyClasses.ConnectionString"]; 

Ora, supponiamo di avere un’applicazione Windows denominata MyApp.exe che fa riferimento a MyClasses.dll. Contiene un app.config con una voce come:

    

O

Un file xml è il migliore equivalente per app.config. Usa serializzare / deselezionare xml secondo necessità. Puoi chiamarlo come vuoi. Se la configurazione è “statica” e non è necessario modificarla, è ansible aggiungerla al progetto come risorsa incorporata.

Spero che dia un’idea

I file di configurazione hanno ambito ambito e non ambito ambito. Quindi dovrai inserire le sezioni di configurazione della tua libreria nel file di configurazione di ogni applicazione che utilizza la tua libreria.

Detto questo, non è una buona pratica ottenere la configurazione dal file di configurazione dell’applicazione, in particolare dalla sezione appSettings , in una libreria di classi. Se la tua libreria ha bisogno di parametri, dovrebbero probabilmente essere passati come argomenti del metodo in costruttori, metodi di fabbrica, ecc. Da chiunque stia chiamando la tua libreria. Ciò impedisce alle applicazioni di chiamata di riutilizzare accidentalmente le voci di configurazione previste dalla libreria di classi.

Detto questo, i file di configurazione XML sono estremamente utili, quindi il miglior compromesso che ho trovato è l’utilizzo di sezioni di configurazione personalizzate. Si arriva a mettere la configurazione della libreria in un file XML che viene automaticamente letto e analizzato dal framework e si evitano potenziali incidenti.

Puoi saperne di più sulle sezioni di configurazione personalizzate su MSDN e anche Phil Haack ha un bell’articolo su di loro.

 public class ConfigMan { #region Members string _assemblyLocation; Configuration _configuration; #endregion Members #region Constructors ///  /// Loads config file settings for libraries that use assembly.dll.config files ///  /// The full path or UNC location of the loaded file that contains the manifest. public ConfigMan(string assemblyLocation) { _assemblyLocation = assemblyLocation; } #endregion Constructors #region Properties Configuration Configuration { get { if (_configuration == null) { try { _configuration = ConfigurationManager.OpenExeConfiguration(_assemblyLocation); } catch (Exception exception) { } } return _configuration; } } #endregion Properties #region Methods public string GetAppSetting(string key) { string result = string.Empty; if (Configuration != null) { KeyValueConfigurationElement keyValueConfigurationElement = Configuration.AppSettings.Settings[key]; if (keyValueConfigurationElement != null) { string value = keyValueConfigurationElement.Value; if (!string.IsNullOrEmpty(value)) result = value; } } return result; } #endregion Methods } 

Solo per fare qualcosa, ho rifattorizzato la risposta più alta in una class. L’utilizzo è qualcosa come:

 ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location); var setting = configMan.GetAppSetting("AppSettingsKey"); 

Se si aggiungono le impostazioni in un progetto Libreria di classi in Visual Studio (Proprietà progetto, Impostazioni), aggiungerà un file app.config al progetto con le sezioni userSettings / applicatioNSettings rilevanti e i valori predefiniti per queste impostazioni da Settings.settings file.

Tuttavia questo file di configurazione non verrà utilizzato in fase di esecuzione, ma la libreria di classi utilizza il file di configurazione della sua applicazione di hosting.

Credo che il motivo principale per la generazione di questo file sia che puoi copiare / incollare le impostazioni nel file di configurazione dell’applicazione host.

In risposta alla domanda originale, di solito aggiungo il file di configurazione nel mio progetto di test come collegamento; è quindi ansible utilizzare l’attributo DeploymentItem per aggiungere alla cartella Out dell’esecuzione di test.

 [TestClass] [DeploymentItem("MyProject.Cache.dll.config")] public class CacheTest { . . . . } 

In risposta ai commenti che gli Assemblies non possono essere specifici del progetto, possono e offrono una grande flessibilità esp. quando si lavora con framework IOC.

gli assembly non hanno il proprio file app.config. Usano il file app.config dell’applicazione che li sta usando. Quindi se il tuo assembly si aspetta determinate cose nel file di configurazione, allora assicurati che il file di configurazione dell’applicazione abbia quelle voci lì dentro.

Se l’assembly viene utilizzato da più applicazioni, ciascuna di queste applicazioni dovrà avere tali voci nel proprio file app.config.

Quello che ti consiglierei di fare è definire le proprietà sulle classi nell’assembly per quei valori, ad esempio

 private string ExternalServicesUrl { get { string externalServiceUrl = ConfigurationManager.AppSettings["ExternalServicesUrl"]; if (String.IsNullOrEmpty(externalServiceUrl)) throw new MissingConfigFileAppSettings("The Config file is missing the appSettings entry for: ExternalServicesUrl"); return externalServiceUrl; } } 

Qui, la proprietà ExternalServicesUrl ottiene il suo valore dal file di configurazione dell’applicazione. Se qualsiasi applicazione che utilizza questo assembly manca quell’impostazione nel file di configurazione, si otterrà un’eccezione o è chiaro che qualcosa è andato perso.

MissingConfigFileAppSettings è un’eccezione personalizzata. Potresti voler lanciare un’eccezione diversa.

Naturalmente un design migliore sarebbe per il metodo di quelle classi fornire quei valori come parametri piuttosto che fare affidamento sull’impostazione del file di configurazione. In questo modo le applicazioni che utilizzano queste classi possono decidere da dove e come forniscono questi valori.

Usa aggiungi elemento esistente, seleziona la configurazione dell’app dal progetto dll. Prima di fare clic su aggiungi, utilizza la piccola freccia in giù sul lato destro del pulsante Aggiungi per “aggiungi come collegamento”

Lo faccio sempre nel mio dev.

Attualmente sto creando plugin per un marchio di software al dettaglio, che in realtà sono librerie di class .net. Come requisito, ogni plugin deve essere configurato utilizzando un file di configurazione. Dopo un po ‘di ricerche e test, ho compilato la seguente lezione. Fa il lavoro in modo impeccabile. Si noti che non ho implementato la gestione delle eccezioni locali nel mio caso, perché rilevo eccezioni a un livello superiore.

Alcuni ritocchi potrebbero essere necessari per ottenere il punto decimale giusto, in caso di decimali e doppi, ma funziona bene per il mio CultureInfo …

 static class Settings { static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase); static Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(uri.Path); static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings"); static NumberFormatInfo nfi = new NumberFormatInfo() { NumberGroupSeparator = "", CurrencyDecimalSeparator = "." }; public static T Setting(string name) { return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi); } } 

Esempio di file App.Config

     

Uso:

  somebooleanvar = Settings.Setting("Enabled"); somestringlvar = Settings.Setting("ExportPath"); someintvar = Settings.Setting("Seconds"); somedoublevar = Settings.Setting("Ratio"); 

Crediti per Shadow Wizard e MattC

Preambolo : sto usando NET 2.0;

La soluzione postata da Yiannis Leoussis è accettabile ma ho avuto qualche problema.

Innanzitutto, l’ static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings"); restituisce null. Ho dovuto cambiarlo in static AppSettingSection = myDllConfig.AppSettings;

Quindi il return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi); non ha un fermo per le eccezioni. Quindi l’ho cambiato

 try { return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi); } catch (Exception ex) { return default(T); } 

Funziona molto bene, ma se hai una DLL diversa devi riscrivere ogni volta il codice per ogni assembly. Quindi, questa è la mia versione per una class di istanziare ogni volta che è necessario.

 public class Settings { private AppSettingsSection _appSettings; private NumberFormatInfo _nfi; public Settings(Assembly currentAssembly) { UriBuilder uri = new UriBuilder(currentAssembly.CodeBase); string configPath = Uri.UnescapeDataString(uri.Path); Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(configPath); _appSettings = myDllConfig.AppSettings; _nfi = new NumberFormatInfo() { NumberGroupSeparator = "", CurrencyDecimalSeparator = "." }; } public T Setting(string name) { try { return (T)Convert.ChangeType(_appSettings.Settings[name].Value, typeof(T), _nfi); } catch (Exception ex) { return default(T); } } } 

Per una configurazione:

     

Usalo come:

 Settings _setting = new Settings(Assembly.GetExecutingAssembly()); somebooleanvar = _settings.Setting("Enabled"); somestringlvar = _settings.Setting("ExportPath"); someintvar = _settings.Setting("Seconds"); somedoublevar = _settings.Setting("Ratio"); 

Per quanto ne so, devi copiare + incollare le sezioni che desideri dalla libreria .config nel file .config dell’applicazione. Ottieni solo 1 app.config per istanza eseguibile.

Ho affrontato lo stesso problema e l’ho risolto creando un parametro di class statico dopo aver aggiunto un file di configurazione dell’applicazione al progetto:

 public static class Parameters { // For a Web Application public static string PathConfig { get; private set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web.config"); // For a Class Library public static string PathConfig { get; private set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "LibraryName.dll.config"); public static string getParameter(string paramName) { string paramValue = string.Empty; using (Stream stream = File.OpenRead(PathConfig)) { XDocument xdoc = XDocument.Load(stream); XElement element = xdoc.Element("configuration").Element("appSettings").Elements().First(a => a.Attribute("key").Value == paramName); paramValue = element.Attribute("value").Value; } return paramValue; } } 

Quindi ottieni un parametro come questo:

 Parameters.getParameter("keyName"); 

Perché non usare:

  • [ProjectNamespace].Properties.Settings.Default.[KeyProperty] per C #
  • My.Settings.[KeyProperty] per VB.NET

Devi solo aggiornare visivamente queste proprietà in fase di progettazione attraverso:

[Solution Project]->Properties->Settings

utilizzare da configurazioni deve essere molto molto facile come questo:

 var config = new MiniConfig("setting.conf"); config.AddOrUpdate("port", "1580"); if (config.TryGet("port", out int port)) // if config exist { Console.Write(port); } 

per maggiori dettagli vedi MiniConfig