Digamos que estou criando um aplicativo chamado ConsoleApp2 .
Devido a algumas bibliotecas de terceiros que estou usando, meu arquivo app.config padrão está gerando código como
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Isso é porque minhas referências solução versões diferentes de uma biblioteca, por isso precisa de dizer a todos: " Ei, se você olhar para qualquer OldVersion desta biblioteca, basta usar NewVersion ". E está tudo bem.
O problema é que eu quero definir um arquivo de configuração separado "test.exe.config", onde tenho algumas configurações e me livrar da gerada automaticamente.
Para informar meu aplicativo sobre o novo arquivo de configuração, estou usando um código como
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "test.exe.config");
E isso funciona (quase) perfeitamente. E eu escrevi lá " quase ", pois, embora a <appSettings>
seção esteja sendo lida corretamente, a <runtime>
seção não está sendo analisada no meu arquivo de configuração personalizado, mas o App o procura no arquivo de configuração padrão, o que é um problema, já que eu quero poder excluí-lo mais tarde.
Então, como posso dizer ao meu aplicativo para ler também as <runtime>
informações do meu arquivo de configuração personalizado?
Como reproduzir o problema
Um exemplo simples para reproduzir meu problema é o seguinte:
Crie uma biblioteca chamada ClassLibrary2 ( .Net Framework v4.6 ) com uma única classe da seguinte maneira
using Newtonsoft.Json.Linq;
using System;
namespace ClassLibrary2
{
public class Class1
{
public Class1()
{
var json = new JObject();
json.Add("Succeed?", true);
Reash = json.ToString();
}
public String Reash { get; set; }
}
}
Observe a referência ao pacote Newtonsoft . O instalado na biblioteca é a v10.0.2 .
Agora crie um aplicativo de console chamado ConsoleApp2 ( .Net Framework v4.6 ) com uma classe chamada Program cujo conteúdo é simplesmente o seguinte:
using System;
using System.Configuration;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "test.exe.config");
var AppSettings = ConfigurationManager.AppSettings;
Console.WriteLine($"{AppSettings.Count} settings found");
Console.WriteLine($"Calling ClassLibrary2: {Environment.NewLine}{new ClassLibrary2.Class1().Reash}");
Console.ReadLine();
}
}
}
Este aplicativo deve ter instalado também o Newtonsoft , mas em uma versão diferente v12.0.3 .
Crie o aplicativo no modo de depuração. Em seguida, na pasta ConsoleApp2 / ConsoleApp2 / bin / Debug, crie um arquivo chamado test.exe.config com o seguinte conteúdo
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<appSettings>
<add key="A" value="1"/>
<add key="B" value="1"/>
<add key="C" value="1"/>
</appSettings>
</configuration>
e observe que nessa mesma pasta Debug também há o arquivo de configuração padrão ConsoleApp2.exe.config com um conteúdo como
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Se nesse ponto você executar o aplicativo, ele será compilado sem problemas e você deverá ver um console como
Observe que as (3) configurações foram lidas corretamente no meu arquivo de configuração personalizado. Por enquanto, tudo bem...
Agora renomeie o arquivo de configuração padrão para algo como _ConsoleApp2.exe.config e execute novamente o aplicativo. Agora você deve obter uma FileLoadException .
Então, novamente, como posso dizer ao meu aplicativo para ler as <runtime>
informações do meu arquivo de configuração personalizado?
Fundamentação
A razão pela qual estou procurando uma resposta para esta pergunta é a seguinte:
Quando lançamos nosso aplicativo, colocamos todos os arquivos .exe e .dll em uma pasta e nosso arquivo de configuração personalizado (com configurações, etc) em outra, onde nossos clientes têm arquivos semelhantes.
Na pasta com os arquivos .exe e .dll, tentamos manter o mínimo possível, por isso me pediram para encontrar uma maneira de se livrar desse ConsoleApp2.exe.config, se possível. Agora, desde que as ligações mencionadas acima foram escritas nesse arquivo de configuração, tentei mover essas informações para nosso arquivo de configuração personalizado ... mas até agora não consegui: os redirecionamentos de ligação sempre tentam ser lidos a partir desse ConsoleApp2.exe .config , assim que removê-lo, recebo exceções ...
<runtime>
seção de outra configuração, mas o problema ocorre devido à maneira como você gerencia a configuração comum. Se você gerenciar configurações comuns de uma maneira diferente, esse problema não será mais relevante. Por favor, verifique minha resposta e considere usar transformações de configuração em vez de ajustar o tempo de execução.