Introdução: Uma pergunta que atormenta todo desenvolvedor .NET
\n\nVocê já se perguntou o que realmente acontece quando você escreve ConfigurationManager.AppSettings["myKey"]? A maioria dos desenvolvedores simplesmente aceita isso como garantido: escreveu a string — obteve o valor. Mas se você cavar um pouco mais fundo (e é exatamente isso que toda mente curiosa faz depois de ler uma pergunta popular no Stack Overflow), descobrirá todo um mecanismo escondido por trás dessa chamada simples.
Neste artigo, não vamos apenas mostrar como ler as configurações do app.config ou web.config em C#. Vamos olhar "por baixo do capô": analisar como o .NET Framework faz o parsing do XML, quais classes participam desse processo e por que às vezes suas configurações não são lidas (spoiler: a culpa não é só do cache).
\n\nSe você já se deparou com uma situação em que ConfigurationManager.AppSettings["ConnectionString"] retorna null, mas o arquivo de configuração está ali do lado — este artigo é para você.
1. Fundamentos: Estrutura do arquivo de configuração
\n\nAntes de mergulhar nos detalhes, vamos lembrar como é um app.config típico (ou web.config). Tudo começa com o elemento raiz <configuration>:
<?xml version="1.0" encoding="utf-8" ?>\n<configuration>\n <appSettings>\n <add key="ApiUrl" value="https://api.example.com"/>\n <add key="TimeoutSeconds" value="30"/>\n </appSettings>\n <connectionStrings>\n <add name="MainDb" connectionString="Server=.;Database=MyDb;Trusted_Connection=true;"/>\n </connectionStrings>\n</configuration>\n\nEste arquivo XML não é apenas um conjunto de strings. É uma estrutura rigidamente tipada que o .NET interpreta de uma maneira especial. E é aqui que a coisa fica interessante.
\n\n2. Como funciona o ConfigurationManager: da chamada ao resultado
\n\nQuando você chama ConfigurationManager.AppSettings["ApiUrl"], ocorre a seguinte cadeia de eventos:
- \n
- Determinação do arquivo de configuração. O sistema determina qual arquivo ler. Para uma aplicação, é
YourApp.exe.config(localizado junto ao exe), para uma aplicação web, éweb.configna raiz. Se o arquivo não existir, retorna uma coleção vazia. \n - Carregamento do XML. O arquivo é lido como um documento XML. Usa-se
System.Xml.XmlDocumentou o mais eficienteXmlReader(depende da versão do .NET). \n - Busca da seção. Procura-se o elemento
<configuration>e, dentro dele,<appSettings>. \n - Parsing dos valores. Cada elemento filho
<add>com os atributoskeyevalueé convertido em um par chave-valor e colocado em umNameValueCollection. \n - Cache. O resultado é armazenado em cache. Uma chamada repetida a
ConfigurationManager.AppSettingsnão relê o arquivo — ele obtém os dados do cache. \n
Nuance importante: cache e alterações
\n\nSe você alterar o app.config durante a execução da aplicação, o ConfigurationManager.AppSettings não verá essas alterações até que o domínio da aplicação seja recarregado. Esta é uma das causas mais comuns de bugs: "Eu mudei as configurações, mas o programa ainda usa as antigas!".
Para forçar a releitura da configuração, você pode usar ConfigurationManager.RefreshSection("appSettings"), mas isso é mais um paliativo do que uma solução.
3. Manipuladores de seção: seções personalizadas
\n\nVocê provavelmente já notou que no web.config não existem apenas appSettings, mas também system.web, system.net e outros. Cada uma dessas seções é processada pelo seu próprio manipulador de seção — uma classe que r