Equivalente a ‘app.config’ para uma biblioteca (DLL)

Existe um equivalente a app.config para bibliotecas (DLLs)? Se não, qual é a maneira mais fácil de armazenar configurações específicas de uma biblioteca? Por favor, considere que a biblioteca pode ser usada em diferentes aplicações.

Você pode ter um arquivo de configuração separado, mas você terá que lê-lo “manualmente”, o ConfigurationManager.AppSettings["key"] lerá somente a configuração da assembly em execução.

Supondo que você esteja usando o Visual Studio como seu IDE, você pode clicar com o botão direito do mouse no projeto desejado → Adicionar → Novo item → Arquivo de configuração do aplicativo

Isso adicionará o App.config à pasta do projeto, colocará suas configurações na seção . Caso você não esteja usando o Visual Studio e adicionando o arquivo manualmente, certifique-se de fornecer tal nome: DllName.dll.config , caso contrário, o código abaixo não funcionará corretamente.

Agora, para ler este arquivo tem essa function:

 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 para usá-lo:

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

Você também precisará adicionar referência ao namespace System.Configuration para disponibilizar a class ConfigurationManager.

Ao criar o projeto, além da DLL, você também terá o arquivo DllName.dll.config . Esse é o arquivo que você deve publicar com a própria DLL.

O exemplo acima é um código de exemplo básico, para aqueles interessados ​​em um exemplo de escala completa, por favor consulte esta outra resposta .

Infelizmente, você só pode ter um arquivo app.config por executável, portanto, se você tiver DLLs vinculados ao seu aplicativo, eles não poderão ter seus próprios arquivos app.config.

A solução é: você não precisa colocar o arquivo App.config no projeto da biblioteca de classs.
Você coloca o arquivo App.config no aplicativo que está fazendo referência à dll da sua biblioteca de classs.

Por exemplo, digamos que temos uma biblioteca de classs chamada MyClasses.dll que usa o arquivo app.config da seguinte forma:

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

Agora, digamos que temos um aplicativo do Windows chamado MyApp.exe que faz referência a MyClasses.dll. Ele conteria um App.config com uma input como:

    

OU

Um arquivo xml é o melhor equivalente para app.config. Use xml serialize / desserialize conforme necessário. Você pode chamar o que você quiser. Se sua configuração for “estática” e não precisar ser alterada, você também poderá adicioná-la ao projeto como um recurso incorporado.

Espero que dê alguma ideia

Os arquivos de configuração são do escopo do aplicativo e não do escopo do assembly. Portanto, você precisará colocar as seções de configuração da sua biblioteca no arquivo de configuração de cada aplicativo que está usando sua biblioteca.

Dito isso, não é uma boa prática obter a configuração do arquivo de configuração do aplicativo, especialmente a seção appSettings , em uma biblioteca de classs. Se sua biblioteca precisar de parâmetros, eles provavelmente devem ser passados ​​como argumentos de método em construtores, methods de fábrica, etc. por quem estiver chamando sua biblioteca. Isso evita que os aplicativos de chamada reutilizem acidentalmente as inputs de configuração esperadas pela biblioteca de classs.

Dito isso, os arquivos de configuração XML são extremamente úteis, então o melhor compromisso encontrado é o uso de seções de configuração personalizadas. Você pode colocar a configuração da sua biblioteca em um arquivo XML que é lido e analisado automaticamente pela estrutura e evita possíveis acidentes.

Você pode aprender mais sobre seções de configuração customizadas no MSDN e também o Phil Haack tem um bom artigo sobre elas.

 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 } 

Apenas por algo a fazer, refatorei a resposta principal em uma aula. O uso é algo como:

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

Se você adicionar configurações a um projeto de biblioteca de classs no Visual Studio (propriedades do projeto, configurações), ele adicionará um arquivo app.config ao seu projeto com as seções relevantes userSettings / applicatioNSettings e os valores padrão para essas configurações do seu Settings.settings Arquivo.

No entanto, este arquivo de configuração não será usado em tempo de execução – em vez disso, a biblioteca de classs usa o arquivo de configuração de seu aplicativo de hospedagem.

Acredito que o principal motivo para gerar esse arquivo é para que você possa copiar / colar as configurações no arquivo de configuração do aplicativo host.

Em resposta à pergunta original, normalmente adiciono o arquivo de configuração em meu projeto de teste como um link; Em seguida, você pode usar o atributo DeploymentItem para adicionar à pasta Out da execução de teste.

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

Em resposta aos comentários de que Assemblies não podem ser específicos do projeto, eles podem e oferecem uma grande flexibilidade, esp. ao trabalhar com estruturas do IOC.

assemblies não possuem seu próprio arquivo app.config. Eles usam o arquivo app.config do aplicativo que os está usando. Portanto, se seu assembly está esperando certas coisas no arquivo de configuração, apenas certifique-se de que o arquivo de configuração do seu aplicativo tenha essas inputs lá.

Se o seu assembly estiver sendo usado por vários aplicativos, cada um desses aplicativos precisará ter essas inputs no arquivo app.config.

O que eu recomendaria que você fizesse é definir propriedades nas classs em seu assembly para esses valores, por exemplo

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

Aqui, a propriedade ExternalServicesUrl obtém seu valor do arquivo de configuração do aplicativo. Se algum aplicativo que estiver usando esta assembly estiver faltando essa configuração no arquivo de configuração, você terá uma exceção, o que é claro que algo está faltando.

MissingConfigFileAppSettings é uma exceção personalizada. Você pode querer lançar uma exceção diferente.

É claro que um design melhor seria que o método dessas classs recebesse esses valores como parâmetros, em vez de depender da configuração do arquivo de configuração. Dessa forma, os aplicativos que usam essas classs podem decidir de onde e como eles fornecem esses valores.

Use adicionar item existente, selecione a configuração do aplicativo do projeto dll. Antes de clicar em adicionar, use a pequena seta para baixo no lado direito do botão Adicionar para “adicionar como link”

Eu faço isso o tempo todo no meu dev.

Atualmente, estou criando plugins para uma marca de software de varejo, que na verdade são bibliotecas de classs .net. Como requisito, cada plug-in precisa ser configurado usando um arquivo de configuração. Depois de um pouco de pesquisa e teste, eu compilei a seguinte class. Ele faz o trabalho sem falhas. Note que eu não implementei exception handling local no meu caso porque, eu pego exceções em um nível superior.

Alguns ajustes talvez necessários para obter o ponto decimal certo, no caso de decimais e duplos, mas funciona bem para o meu 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); } } 

Amostra do arquivo App.Config

     

Uso:

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

Créditos ao Shadow Wizard e MattC

Preâmbulo : estou usando o NET 2.0;

A solução postada por Yiannis Leoussis é aceitável, mas eu tive algum problema com isso.

Primeiro, a static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings"); retorna nulo. Eu tive que mudá-lo para static AppSettingSection = myDllConfig.AppSettings;

Em seguida, o return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi); não tem uma pegada para exceções. Então eu mudei

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

Isso funciona muito bem, mas se você tiver uma dll diferente, você terá que rewrite toda vez que o código para cada assembly. Então, esta é a minha versão para uma class para instanciar toda vez que você precisar.

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

Para uma configuração:

     

Use-o como:

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

Tanto quanto eu sei, você tem que copiar + colar as seções que você quer da biblioteca .config no arquivo .config de aplicativos. Você só recebe 1 app.config por instância executável.

Eu enfrentei o mesmo problema e resolvi isso criando uma class estática Parameters depois de adicionar um arquivo de configuração do aplicativo ao projeto:

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

Então pegue um parâmetro como este:

 Parameters.getParameter("keyName"); 

Por que não usar:

  • [ProjectNamespace].Properties.Settings.Default.[KeyProperty] para c #
  • My.Settings.[KeyProperty] para VB.NET

Você só precisa atualizar visualmente essas propriedades em tempo de design por meio de:

[Solution Project]->Properties->Settings

O uso de configurações deve ser muito fácil assim:

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

para mais detalhes veja MiniConfig