2009-07-27 10 views
6

He intentado descifrar éste en las últimas semanas y aún no he encontrado una buena solución; con suerte puedo obtener una respuesta aquí.Cargando 2 versiones de ensamblaje en el tiempo de ejecución

Tengo dos conjuntos (ZA & ZB), que apuntan a un proyecto/dll común (ZC) pero que podrían tener una versión diferente (es decir, el mismo nombre dll, los mismos espacios de nombres, algunas clases pueden ser diferentes) . Cada ensamblaje funciona solo, sin embargo, si uno es cargado por el otro en tiempo de ejecución (por ejemplo, A carga B), entonces no puedo hacer que funcione. Necesito ayuda.

Aquí está la configuración:

  • ZA depende de ZC versión (común) 1.1
  • ZB depende de la versión ZC 1,0

ZA necesita cargar necesidades para cargar algo en ZB (que depende de ZC), en tiempo de ejecución.

ZA es la aplicación maestra. En su directorio bin, hay un directorio de complementos plugins/plugin-ZB en el que me gustaría colocar todos los ZB y sus dependencias (ZC).

Aquí es lo que he probado hasta ahora:

Assembly.Load() usando misma versión de DLL - funcionaba bien.

Assembly.Load() usando diferentes versiones de cargas dll-ZB, pero cuando se ejecuta el método, obtengo una excepción de método no encontrado.

AppDomain.Load() obtuvo un error de archivo no encontrado; Incluso usé el delegado para resolver ensamblajes.

Algunos detalles sobre ZC: - algunos métodos son públicos estáticos (algunos no). P.ej. Log.Log("hello"); - algunos pueden devolver valores (primitivos u objetos). - algunos métodos no son estáticos (y devuelven valores).

¿Ayuda? - TIA

Respuesta

1

Además de Jonathan Allen, un excelente consejo, una forma más "clásica" de resolver el problema es cargar las 2 versiones en 2 AppDomanis diferentes. Luego puede usar .NET Remoting para hacer que los dos AppDomains se comuniquen. Entonces ZA debería crear un nuevo Appdomain, cargar en este AppDomain ZB e invocar alguna operación en ZB a través de Remoting.

Tenga en cuenta que .NET Remoting tiene algunos requisitos sobre las clases que desea utilizar (herencia de MarshalByRef), y la creación de un AppDomain es una operación costosa.

Esperanza esta ayuda

+0

"Sólo puede tener una versión de un conjunto para un dominio de aplicación" no es cierto. Incluso es posible hacer referencia a dos versiones de un ensamblaje desde un único ensamblaje, buscar alias externo para obtener más información, esto es lo primero que aparece en Google con un ejemplo de la función: http://blogs.msdn.com/ b/ansonh/archive/2006/09/28/extern-alias-walkthrough.aspx – Graham

+0

Sin embargo, el uso de dos AppDomains es una solución al problema descrito. – Graham

+0

¡Bien, respuesta actualizada! –

0

he tenido dos versiones del mismo ensamblado cargado al mismo tiempo. Sucedió con un escenario tal como lo describes.

Tienes que convencer al motor de ejecución de cargar la misma versión de ZC para ZA y ZB. He encontrado dos formas de hacerlo:

  1. Utilice un elemento bindingRedirect en su archivo App.config. Hay algunos detalles en this question.
  2. Utilice el evento AppDomain.AssemblyResolve. Hay algunos detalles en this answer.

El único problema con AppDomain.AssemblyResolve es que solo se activa cuando el motor de ejecución no puede encontrar la versión solicitada. Si ambas versiones están disponibles, entonces tendrá que usar el bindingRedirect. Utilicé el evento AppDomain.AssemblyResolve y luego agregué un control de seguridad que asegura que la versión correcta se cargó mirando a través de la colección de ensamblajes referenciada del ensamblaje. Si no es así, me quejo al usuario de que hay una versión anterior de la biblioteca y le digo dónde está.

+1

Esto no está cargando dos versiones diferentes, está cargando la misma versión dos veces. –

+1

Cuando tuve este problema, @Cameron, el tiempo de ejecución cargó la versión 1.1 de ZC cuando ZA comenzó. Luego, cuando cargué el conector ZB, el tiempo de ejecución cargó la versión 1.0 de ZC con él. A eso me refiero cargando dos versiones diferentes. Para hacer que ZA y ZB pasen objetos de ZC entre ellos, tuve que hacer que ambos cargaran la misma versión de ZC. Eso es lo que estoy describiendo cómo hacer en mi respuesta. ¿He entendido mal la pregunta original? –

3
m_Assembly1 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "Old Version\Some.dll")) 
    m_Assembly2 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "New Version\Some.dll")) 

    Console.WriteLine("Old Version: " & m_Assembly1.GetName.Version.ToString) 
    Console.WriteLine("New Version: " & m_Assembly2.GetName.Version.ToString) 

    m_OldObject = m_Assembly1.CreateInstance("FullClassName") 
    m_NewObject = m_Assembly2.CreateInstance("FullClassName") 

De aquí en adelante utilicé el encuadernado y/o reflejo tardíos para ejecutar mis pruebas.

.NET: Load two version of the same DLL

+0

¡Excelente consejo! no sabía eso –

Cuestiones relacionadas