2009-11-16 33 views
7

Mi proyecto de Visual Studio 2008 hace referencia a dos ensamblajes (externos) (A + B) que hacen referencia al mismo tercer ensamblaje (C). Sin embargo, el conjunto A espera que el conjunto C tenga una clave pública que es diferente de lo que el conjunto B espera que tenga.Referencia dos ensamblados iguales, solo las claves públicas son diferentes

He aquí un ejemplo de la excepción obvia:

No se pudo cargar el archivo o ensamblado 'Newtonsoft.Json, Version = 3.5.0.0, Culture = neutral, PublicKeyToken = 9ad232b50c3e6444' o uno de sus dependencias. La definición del manifiesto del ensamblaje ubicado no coincide con la referencia de ensamblaje. (Excepción de HRESULT: 0x80131040)

Por supuesto, yo no sería capaz de poner las dos versiones del C (sólo se diferencian por la clave pública) en el mismo directorio, ya que sus nombres de archivo son iguales. En segundo lugar, descubrí que usar el enlace de ensamblaje desde el archivo de configuración solo permite el mapeo de versión, no el mapeo de clave pública.

También traté de colocar uno de los ensamblajes C en un directorio aparte y configurar el CLR para buscar en ese directorio al cargar ensamblajes. No pude hacer que eso funcione por desgracia.

Soy consciente de que volver a compilar una de las bibliotecas externas (uno de ellos pasa a ser de código abierto) sería solucionar este problema, pero no quiero añadir que carga para mi plan de mantenimiento si no es absolutamente necesario.

Así que mi pregunta es: ¿cómo haría referencia a las dos "versiones" del conjunto C, que solo difieren en clave pública?

ACTUALIZACIÓN

yo nos topamos con this answer a una pregunta relacionada, proporcionando una solución interesante usando ILMerge. Todavía no lo he comprobado, pero puede ser útil para cualquier persona que tenga problemas con este problema.

+1

tuve un problema similar y [esto] (http://stackoverflow.com/questions/2460542/using-different-versions-of-the-same-assembly-in-the-same-folder/2461746#2461746) es como lo resolví –

Respuesta

3

me pregunto si AssemblyResolve funcionaría:

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 

static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    if (args.Name == "full name with old key") 
    { 
     return typeof(SomeTypeInReferencedAssembly).Assembly; 
    } 
    return null; 
} 

He're Estoy asumiendo que usted ha hecho referencia a su versión preferida y puede utilizar el tipo SomeTypeInReferencedAssembly para obtener el Assembly; también se puede utilizar:

return Assembly.Load("full name with new key"); 

Yo no lo he probado, pero aquí esencialmente que estoy diciendo "desplegar una versión de la DLL, y cuando el sistema pide el viejo - mentira".

+0

Gracias, esa es una gran solución. Ahora esperemos que algún día uno de los ensamblados de referencia cambie su referencia a C. –

+0

En realidad, no funciona para mí: ahora dice que el manifiesto de ensamblaje del tipo I return no coincide con el manifiesto de la referencia. Tiene un punto allí ... –

+0

¿Podría publicar el código ofensivo en su pregunta, Sandor? –

3

Nunca se debe tener dos conjuntos con la misma versión pero diferentes claves públicas, eso es una receta para el desastre. Si las versiones reales del ensamblaje son diferentes, entonces la solución más fácil es ubicarlas en el global assembly cache (GAC). Sin embargo, esto no funcionará muy bien si se trata de instancias de tipos definidos en C y utilizados tanto en A como en B (por ejemplo, C declara MyType, y obtiene una instancia de MyType de B y la pasa A. En lo que respecta al tiempo de ejecución, estos dos tipos no tienen absolutamente nada que ver uno con otro aparte de compartir un nombre).

Si está buscando una solución temporal, entonces yo iría con la de Marc; parece que debería funcionar perfectamente.Dicho esto, sin embargo, el hecho de que vayas por este camino debería ser una bandera roja gigante.

+0

Tienes toda la razón. Afortunadamente, en este caso, nunca tendré que pasar tipos alrededor de A y B porque no tienen nada que ver el uno con el otro. Estoy usando la solución de Marc como una solución temporal ahora hasta que A o B cambien su referencia a C. Sé que esto es un poco malo, pero supongo que no hay otra forma adecuada que no sea arrojar A o B. –

Cuestiones relacionadas