Digamos que estoy creando una aplicación llamada ConsoleApp2 .
Debido a algunas bibliotecas de terceros que estoy usando, mi archivo app.config predeterminado genera 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>
Esto se debe a que mi solución hace referencia a diferentes versiones de una biblioteca, por lo que debe decirles a todos: " Oye, si buscas alguna versión antigua de esta biblioteca, solo usa la nueva versión ". Y eso está bien.
El problema es que quiero definir un archivo de configuración separado "test.exe.config" donde tengo algunas configuraciones y deshacerme del generado automáticamente.
Para informar a mi aplicación sobre el nuevo archivo de configuración, estoy usando un código como
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "test.exe.config");
Y eso funciona (casi) perfectamente. Y escribí allí " casi " ya que aunque la <appSettings>
sección se está leyendo correctamente, la <runtime>
sección no se está mirando en mi archivo de configuración personalizado, pero la aplicación lo busca en el archivo de configuración predeterminado, lo cual es un problema ya que quiero poder borrar eso más tarde.
Entonces, ¿cómo puedo decirle a mi aplicación que lea también la <runtime>
información de mi archivo de configuración personalizado?
Cómo reproducir el problema
Una muestra simple para reproducir mi problema es la siguiente:
Cree una biblioteca llamada ClassLibrary2 ( .Net Framework v4.6 ) con una sola clase de la siguiente manera
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; }
}
}
Tenga en cuenta la referencia al paquete Newtonsoft . El que está instalado en la biblioteca es v10.0.2 .
Ahora cree una aplicación de consola llamada ConsoleApp2 ( .Net Framework v4.6 ) con una clase llamada Programa cuyo contenido es simplemente el siguiente:
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();
}
}
}
Esta aplicación debería haber instalado también Newtonsoft , pero en una versión diferente v12.0.3 .
Compile la aplicación en modo de depuración. Luego, en la carpeta ConsoleApp2 / ConsoleApp2 / bin / Debug, cree un archivo llamado test.exe.config con el siguiente contenido
<?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>
y tenga en cuenta que en esa misma carpeta de depuración también está el archivo de configuración predeterminado ConsoleApp2.exe.config con un contenido 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>
Si en este momento ejecuta la aplicación, se compilará sin problemas y debería ver una consola como
Tenga en cuenta que la configuración (3) se leyó correctamente desde mi archivo de configuración personalizado. Hasta aquí todo bien...
Ahora cambie el nombre del archivo de configuración predeterminado a algo como _ConsoleApp2.exe.config y vuelva a ejecutar la aplicación. Ahora debería obtener una FileLoadException .
Entonces, de nuevo, ¿cómo puedo decirle a mi aplicación que lea la <runtime>
información de mi archivo de configuración personalizado?
Razón fundamental
La razón por la que estoy buscando una respuesta a esta pregunta es la siguiente:
Cuando lanzamos nuestra aplicación, colocamos todos los archivos .exe y .dll en una carpeta y nuestro archivo de configuración personalizado (con configuraciones, etc.) en otra, donde nuestros clientes tienen archivos similares.
En la carpeta con los archivos .exe y .dll, tratamos de mantener la menor cantidad posible, por lo que me pidieron que encontrara una forma de deshacerme de esa ConsoleApp2.exe.config si es posible. Ahora, dado que los enlaces mencionados anteriormente se escribieron en ese archivo de configuración, intenté mover esa información a nuestro archivo de configuración personalizado ... pero hasta ahora no he logrado: las redirecciones de enlace siempre se intentan leer desde ese ConsoleApp2.exe .config , así que tan pronto como lo elimino , obtengo excepciones ...
<runtime>
sección desde otra configuración, pero el problema ocurre debido a la forma en que administra la configuración común. Si administra la configuración común de una manera diferente, este problema ya no es relevante. Verifique mi respuesta y considere usar transformaciones de configuración en lugar de ajustar el tiempo de ejecución.