2010-03-16 13 views
7

Tengo un proyecto que tiene un conjunto de dependencias binarias (dlls de ensamblaje para las que no tengo el código fuente). En el tiempo de ejecución, esas dependencias se requieren preinstaladas en la máquina y, en el momento de la compilación, son necesarias en el árbol fuente, por ejemplo en una carpeta lib. Como También estoy haciendo el código fuente disponible para este programa me gustaría permitir que una simple descarga y adquirir experiencia para ello. Desafortunadamente no puedo redistribuir los dlls, y eso complica las cosas, ya que VS no vinculará el proyecto sin acceso a los dlls referenciados.Construir un proyecto de Visual Studio sin acceso a dlls referenciadas

¿Hay alguna forma de permitir que este proyecto se construya y se vincule en ausencia de los dlls reales a los que se hace referencia?

Quizás hay una manera de decirle a VS que se vincule con un trozo generado automáticamente del dll, para que pueda reconstruirse sin el original? Tal vez hay una herramienta de terceros que hará esto? ¿Alguna pista o mejores prácticas en esta área?

Me doy cuenta de que la persona debe tener acceso a los dlls para ejecutar el código, por lo que tiene sentido que pueda agregarlos al proceso de compilación, pero solo intento ahorrarles el dolor de recopilar todos los dlls y colocándolos en la carpeta lib manualmente.

+0

¿Sería aceptable el uso de los archivos DLL necesarios desde el GAC en la máquina de desarrollo? –

+0

Lo haría, pero no tiene sentido exigir que los conjuntos se DONDE EN la máquina de desarrollo, ya que el trabajo de ponerlos allí es más o menos lo mismo que el trabajo de ponerlos en la carpeta de la tapa. –

Respuesta

2

Tal vez una de estas ideas le ayudará a resolver el problema:

  • las interfaces se derivan de todas las clases en las DLL de 3 ª parte. Coloque estas interfaces en un proyecto propio (misma solución) y agregue una referencia a este conjunto de interfaz. También agregue un manejador de eventos al AppDomain.AssemblyResolve e intente encontrar y cargar los ensamblados en tiempo de ejecución. (Los créditos van a NG)
    • Dependiendo de qué tan grande sean los dlls y con qué frecuencia se realizan cambios en la parte pública, esto puede ser muy doloroso.
  • Proporcione un archivo readme.txt en el que explique cómo obtener los ensamblajes necesarios y dónde debe colocarlos el usuario en relación con la ruta del proyecto. Normalmente, VS es lo suficientemente inteligente como para eliminar el signo de exclamación justo después de colocar el conjunto en el lugar correcto, donde el proyecto lo referencia (quizás deba presionar Actualizar en el Explorador de soluciones) (Créditos van a Paul)
    • Don 't olvides de añadir el readme.txt también para su solución haciendo clic derecho sobre su solución y seleccionar 'Añadir -> elemento existente'. En este caso, ocupará un lugar destacado en el estudio visual Solution Explorer y el usuario podrá leerlo con un doble clic.
  • Cree otro proyecto dentro de su solución que pueda descargar automáticamente todos los dlls necesarios y ponerlos en el lugar correcto. Tal vez debería verificar de antemano si estos archivos necesarios ya están allí antes de que comience la descarga. Establezca las Dependencias del proyecto de su proyecto original, de modo que dependerá de este. Por lo tanto, siempre se construirá antes que tu original. Luego, inicie esta herramienta auxiliar de descarga en el evento de preconstrucción de su proyecto original y no olvide salir de su programa con un valor int. 0 significa éxito, cualquier otro error y también Visual Studio sabe si su herramienta fue exitosa y detiene el proceso de compilación antes de colgarse en dlls faltantes.
    • Quizás sea casi imposible descargar automáticamente los archivos, porque necesita un inicio de sesión en una página web o se utilizan algunas cookies, flash, captcha, etc. que no se pueden automatizar con una herramienta.
+0

Por ahora iba con la estrategia de archivo readme.txt. La estrategia de interfaces básicamente es hacer manualmente lo que deseo que sea automático. Además, no me gustaría complicar mi programa con este nivel adicional de indirección. La tercera estrategia suena bien, pero es un trabajo de hellalota y de las dlls y no está disponible públicamente en la web ... –

+0

Si bien esta no es en absoluto la solución al problema, la acepto porque parece que no existe tal herramienta . –

+0

@David: Tal vez sea posible obtener algo de automatización en la creación de un contenedor utilizando Dynamic Proxy: http://www.castleproject.org/dynamicproxy/index.html Nunca lo usé, pero tal vez se pueda usar para la primera sugerencia – Oliver

0

Bien ellas sino el dolor de recoger todas las asambleas y colocarlos en la carpeta lib mismo. Luego, envíelos junto con el código fuente en el repositorio. De esta forma, las personas que revisen el código del repositorio también obtendrán todo lo necesario para compilar el proyecto.

+0

El op dijo "Desafortunadamente no puedo redistribuir los dlls" – pondermatic

0

Una posibilidad bastante drástica sería utilizar el patrón de interfaz separado y cargar programáticamente los dlls en tiempo de ejecución.

+0

Eso sería mucho trabajo. No creo que los beneficios de agilizar la compilación para las personas que descargan el código fuente lo paguen. –

0

Prefiero tener una dependencia de tiempo de compilación que fallar en mi compilación que un error de tiempo de ejecución que podría llevar algún tiempo rastrear.

Coloque un archivo Readme.txt en su solución y explique de forma explícita cuáles son las dependencias, dónde obtenerlas y qué hacer con ellas.

+0

La mayoría de las personas no cambiarán el código, por lo que simplemente descargarán los binarios, que ya hacen la validación de la dependencia y fallarán correctamente cuando no estén allí. En el momento de la compilación, por otro lado, no es necesario el código de dependencia real para ejecutar, solo las firmas de funciones, así que solo estaba vagando si había una forma de informar al compilador de esas para que no necesite las dlls reales. En cuanto al archivo Léame, eso es lo que he estado haciendo hasta ahora. –

2

Para todos los buenos consejos anteriormente, de acuerdo. Dicho esto, tal vez haya un escenario válido en el que las DLL externas generalmente no son necesarias. Así que aquí está lo que haces. Envuelve y aísla. (Es un nivel de abstracción más alto que la creación de interfaces, por lo que es un poco más fácil de mantener).

En Visual Studio, si no recompila los proyectos VS específicos que hacen referencia a las DLL externas, entonces puede salirse con la suya compilando el resto de los proyectos de la solución VS sin tener esas DLL a mano. Por lo tanto, si de alguna manera envuelve las DLL externas con sus propias DLL y luego las distribuye como solo binarias, la persona que comparte su código fuente no necesitará las DLL externas para compilar la solución principal.

Consideraciones: 1. Trabajo adicional para separar el código del contenedor en Proyectos aislados. 2. Los otros proyectos VS debe agregar referencias a sus envoltura de DLL como referencias "Sistema de archivos" en una carpeta "lib", en lugar de "referencias de proyecto". 3. Las configuraciones de VS Solution deben deshabilitar la compilación para las DLL del contenedor. Se debe agregar una nueva configuración para volver a compilar explícitamente, si es necesario. 4. La definición del Proyecto VS para cada una de las DLL de Wrapper debe incluir un evento posterior a la compilación para copiarlos a la ubicación de la carpeta "LIB" esperada. 5. En tiempo de ejecución, las DLL externas deben estar presentes en el directorio bin de la aplicación, o en el GAC de la máquina, o deben cargarse explícitamente. NOTA: Si faltan, solo cuando invocaron realmente en el tiempo de ejecución su ausencia dará como resultado un error de tiempo de ejecución. es decir, no necesita tenerlos si el código no los llama en una situación general. 6. En tiempo de ejecución, se puede coger errores cargar la DLL externa y presentar un mensaje de error al usuario bastante que decir "Para el usuario de esta función, por favor instale el producto siguiente: XYZ". Que es mejor que se muestra "AssemblyLoadException ... por favor utilice FusionLogViewer ... etc" 7. Al inicio de la aplicación, se puede probar y detectar la falta de DLL y luego desactivar funciones específicas que dependen de ellos.

Por ejemplo: De acuerdo con este patrón podría tener una aplicación que se integra con Microsoft CRM y SAP, pero sólo para una función específica, es decir, importación/exportación.
En tiempo de diseño, si el desarrollador no neeeds cambiar el envoltorio, que será capaz de volver a compilar sin que estos DLL externa. En tiempo de ejecución, si el usuario nunca invoca esta función, la aplicación nunca invocará el contenedor y, por lo tanto, las DLL externas no son necesarias.

+0

Eso definitivamente puede resolver el problema, pero el beneficio que trae, las personas que tienen más dificultades para compilar la fuente, no pagan el trabajo extra. Si el trabajo fue realizado por una herramienta, tal vez la balanza se inclinaría al otro lado :-) –

+1

. Dudo que haya alguna herramienta que pueda rediseñar su aplicación para que se acople a sus dependencias. Háganos saber lo que encuentra :) –

+0

¿Qué rediseño hay en los métodos de stubing? Para cada método invocado en la aplicación del ensamblado X, incluya un método de código auxiliar con cuerpo vacío en un nuevo conjunto Y, que a su vez puede reemplazar a X en el proceso de compilación. Para mí no me parece ciencia espacial ;-) –

Cuestiones relacionadas