2008-11-28 10 views
6

Estoy intentando cambiar el enlace de ensamblaje (de una versión a otra) dinámicamente.cómo actualizar la sección assemblyBinding en el archivo config en tiempo de ejecución?

He probado este código, pero no funciona:

 Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
     ConfigurationSection assemblyBindingSection = config.Sections["assemblyBinding"]; 

     assemblyBindingSection.SectionInformation.ConfigSource = "bindingConf.xml"; 
     config.Save(ConfigurationSaveMode.Modified); 

     ConfigurationManager.RefreshSection("assemblyBinding"); 

con bindingConf.xml que contiene la configuración de la sección assemblyBinding.

¿Puede cambiar esta sección en el tiempo de ejecución? ¿cómo hacerlo? ¿Qué alternativas tengo?

Respuesta

17

La mejor manera que he encontrado para vincular dinámicamente a una versión diferente de un conjunto es conectar el evento AppDomain.AssemblyResolve. Este evento se activa siempre que el tiempo de ejecución no pueda localizar el ensamblaje exacto con el que se vinculó la aplicación, y le permite proporcionar otro ensamblaje, que usted cargará en su lugar (siempre que sea compatible).

Por ejemplo, se puede poner en un constructor estático de la clase principal de la aplicación que enlaza el evento como éste:

using System.Reflection; 

static Program() 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e) 
    { 
     AssemblyName requestedName = new AssemblyName(e.Name); 

     if (requestedName.Name == "AssemblyNameToRedirect") 
     { 
      // Put code here to load whatever version of the assembly you actually have 

      return Assembly.LoadFrom("RedirectedAssembly.DLL"); 
     } 
     else 
     { 
      return null; 
     } 
    }; 
} 

Este método evita la necesidad de hacer frente a las fijaciones de montaje en archivos de configuración y es una un poco más flexible en términos de lo que puedes hacer con él.

+1

¡Gran solución! Lamentablemente, en mi caso, necesito el enlace incluso si se resuelve el ensamblaje predeterminado. Entonces el evento nunca será despedido. –

+0

Quizás esta es una posibilidad remota, pero ¿puede vincularse con una versión que sabe que no existirá? (es decir, crea uno especial con un número de versión falso) –

+0

Ohoh ¡Voy a intentar esto! ¡Gracias! –

3

RuntimeSection de la actualización del archivo de configuración en tiempo de ejecución utilizando este código:

private void ModifyRuntimeAppConfig() 
{ 
    XmlDocument modifiedRuntimeSection = GetResource("Framework35Rebinding"); 

    if(modifiedRuntimeSection != null) 
    { 
    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
    ConfigurationSection assemblyBindingSection = config.Sections["runtime"]; 

    assemblyBindingSection.SectionInformation.SetRawXml(modifiedRuntimeSection.InnerXml); 
    config.Save(ConfigurationSaveMode.Modified); 
    ConfigurationManager.RefreshSection("runtime"); 
    } 
} 

con Framework35Rebinding que contiene:

<runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
    <dependentAssembly> 
     <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/> 
     <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="3.5.0.0"/> 
    </dependentAssembly> 
    <dependentAssembly> 
     <assemblyIdentity name="Microsoft.CompactFramework.Build.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/> 
     <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="9.0.0.0"/> 
    </dependentAssembly> 
    </assemblyBinding> 
</runtime> 

y un app.config que contiene (antes de la ejecución del programa):

<?xml version="1.0"?> 
<configuration> 
    <startup> 
    <supportedRuntime version="v2.0.50727"/> 
    </startup> 
    <runtime> 
    </runtime> 
</configuration> 

Sin embargo, no funciona para eso quiero porque assem blyBinding solo se lee al inicio de la aplicación mientras que RefreshSection("runtime")

Cuestiones relacionadas