2012-07-04 9 views
9

¿Cuál es la mejor práctica en el mundo de .NET para administrar dependencias transitivas que causan conflictos de versión?Dependencia transitiva que causa una versión conflictiva de la misma DLL

En detalles: Proyecto A depende de Proyecto B que a su vez depende de biblioteca C

también

Proyecto A también depende de Proyecto X que depende de una (potencialmente) versión incompatible de biblioteca diferente y C.

A-> B-> Cv1.0
&
A-> X-> Cv2.0
donde
Cv1 0.0 <> Cv2.0

  • ¿Hay una manera de hacer este trabajo?

  • ¿Se puede hacer SIN usar el GAC?

  • ¿Se puede hacer incluso si B y X están en formato binario solamente (fuente no accesible)?

En otras palabras, hay una manera en que yo pueda tener el proyecto B y X cada uno con sus propias dependencias cuando se usan juntos en el proyecto A sin causar conflictos.

NOTA: Me doy cuenta de que, idealmente, no debería tener este problema en absoluto, pero a medida que se expanda la dependencia de las bibliotecas externas, esto será un efecto secundario inevitable. Entonces me pregunto si debería ocurrir la mejor forma de lidiar con eso.

+1

Idealmente, debería volver a compilar o actualizar B para que dependa de la versión actual de C. Si no puede hacerlo, puede intentar reasignar las versiones. http://stackoverflow.com/a/11126867/48082 ¡Esto no está garantizado para funcionar! – Cheeso

+1

Estoy de acuerdo en que idealmente uno debe limpiar sus proyectos para evitar la situación en el primer lugar, pero esto no siempre es posible, de ahí la pregunta. – Newtopian

+0

reasignando DLL de alguna manera es bueno solo si ambas versiones son compatibles entre sí. El peor escenario posible es que, en caso de que no sean compatibles, existe una forma de que cada una de las dependencias intermedias utilice la versión para la que fue creada y aún realizar el trabajo que el proyecto principal espera de ellas. – Newtopian

Respuesta

4

Hay muchas preguntas similares en Stack Overflow. Por ej. Referencing 2 different versions of log4net in the same solution

Resumen:

  1. Asegúrese de que se implementa el conjunto C en carpetas 1.0 y 2.0, respectivamente, dentro de la carpeta que contiene el ejecutable principal.
  2. archivo app.config Cambio e incluyen algo así como lo siguiente:
<configuration> 
    <runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
     <assemblyIdentity name="C" publicKeyToken="C's public key token" /> 
     <codeBase version="version string for C1.0 e.g. 1.0.0.0" href="1.0\C.dll" /> 
     <codeBase version="version string for C2.0 e.g. 2.0.0.0" href="2.0\C.dll" /> 
     </assemblyIdentity> 
     </dependentAssembly> 
    </assemblyBinding> 
    </runtime> 
</configuration> 

se puede obtener el símbolo de clave pública de C usando SN -T C.dll

Si v1. 0 y v2.0 de C tienen una clave pública diferente (aunque idealmente no deberían) y luego incluyen dos etiquetas de Conjunto dependiente.

+1

, de hecho, hay muchas preguntas, pero ninguno realmente respondió mi pregunta. Mi comprensión de AssemblyBinding fue que permite especificar qué DLL se utiliza para cada espacio de nombres y redirigir las llamadas en consecuencia. Aquí, cada ruta de llamada finalmente apuntará a una sola DLL. En el escenario que expuse, tenemos dos rutas de llamada idénticas que deben estar orientadas a dos DLL diferentes. La única diferencia es que cada uno se llama desde una DLL "principal" diferente. Eso es a menos que no haya entendido correctamente el propósito de la unión. – Newtopian

+0

Tha dijo que supongo que si el editor de las dos dependencias (B y X en el ejemplo anterior) cableara específicamente las versiones de dependencia DLL (C arriba) al producir sus bibliotecas, todo funcionaría (siempre que ambos C Dll sean identificables de manera única archivos, es decir, nombre y/o rutas diferentes). Tendré que experimentar un poco con assemblyBinding ver qué se puede hacer – Newtopian

+0

Si C tiene un nombre fuerte, lo anterior debería funcionar y debería poder cargar la versión correcta de C para B y X. Si no tiene un nombre fuerte pero aún tiene una versión (como se especifica a través del atributo AssemblyVersion), entonces puede experimentar eliminando publicKeyToken y ver si aún funciona. Si eso no funciona, creo que solo espero que sea el evento AssemblyResolve. Trataré de verificar todos estos ifs y peros y compartir los resultados. –

Cuestiones relacionadas