2011-08-27 9 views

Respuesta

18

acabo de estar un poco de experimentación, y parece que ninguna asamblea indirectamente referencia que tiene un tipo directamente referenciado por código en otra asamblea será copiado. Si no hay nada en el código, no lo será. Aquí está mi escenario de ejemplo:

  • MainProgram: aplicación de consola con una referencia directa a DirectAssembly. Código de principal:

    var foo = new DirectAssembly.SampleClass(); 
    
  • DirectAssembly: biblioteca de clase con una referencia directa a IndirectAssembly. Contiene SampleClass:

    public class SampleClass 
    { 
        // Comment out this line to change the behaviour... 
        IndirectAssembly.IndirectClass neverUsed = null; 
    
        public SampleClass() 
        { 
         object x = Activator.CreateInstance("IndirectAssembly", 
                  "IndirectAssembly.IndirectClass"); 
    
        } 
    } 
    
  • IndirectAssembly: Contiene una clase pública IndirectClass con un constructor sin parámetros pública

Como se describió anteriormente, que funciona porque IndirectAssembly se copia en la carpeta de salida de MainProgram. Si comenta la línea indicada en SampleClass, IndirectAssembly es no copiado (aunque siga siendo una referencia) y el código fallará en el momento de la ejecución.

No estoy diciendo que estos son todos las reglas, pero son, al menos, un comienzo ...

+2

+1 Si los tipos de otros ensambles se referencian directamente, se copiarán. He tenido ocasión de hacer referencias explícitas a tipos, que normalmente se cargarían dinámicamente para que se desplegaran. –

+0

¡Pero no deberíamos tener que hacer esto! – binki

+0

@binki: Estoy de acuerdo, es un problema, y ​​con NuGet en ASP.NET 5 es mucho mejor. Pero al menos saber lo que se necesita ayuda ... –

2

Debe copiar todas las referencias recursivas. Por ejemplo:

enter image description here

--- --- EDITAR

Las reglas (al menos en VS2010) parece ser como sigue:

  • una referencia indirecta se copia solo si se usa realmente
  • Se copia una referencia directa sin importar qué, incluso si no se usa realmente.

Por lo tanto, si desea asegurarse de que se implementa el ensamblado requerido para la reflexión, hágalo desde el proyecto raíz.

Por cuestiones de reflexión, parece ser suficiente agregar el conjunto mínimo de referencias en cada nivel de la jerarquía del proyecto.

+0

y ¿qué ocurre si se elimina el uso del conjunto de C (pero se mantiene la referencia) de B? No copiará el ensamblaje C. ¿Y qué ocurre si se usa el conjunto C por reflexión? No copiará el conjunto C – SiberianGuy

+0

@Idsa: Sí, eso es exactamente lo que estaba escribiendo también. –

+1

@Idsa El punto acerca de la reflexión es válido. En cuanto a mantener la referencia "innecesaria" de B a C, es cierto que la C no se copiará a 'bin', pero tampoco habrá ** error ** en tiempo de ejecución. –

1

Mi experiencia es que copia los montajes de todos directamente referenciados de forma recursiva, - es decir, nada directamente referenciado en su código, y cualquier cosa que estos referencia también.

No se hará referencia a todo lo que no se haga referencia en tiempo de compilación en su código. Por lo tanto, las referencias que solo se resuelven en tiempo de ejecución no se copiarán. Esto se debe a que, aunque puede saber exactamente a qué se refiere, el copmpiler no. Ya sea reflejando o usando el activador para referenciarlo (como en las dos respuestas ya dadas) porque en tiempo de compilación, no se puede determinar el tipo real de los objetos.

Las referencias en el proyecto indican dónde deben resolverse las referencias de código, pero eso es todo, creo que la evidencia es que no se copiarán, todo está basado en las referencias codificadas de tiempo de compilación.

Esta es una razón por la cual algunas de las técnicas de inyección pueden funcionar, antes de que la resolución de la referencia no sea necesaria en el momento de la compilación o incluso del despliegue.

5

Hay una sutileza no abordada en las respuestas anteriores, es decir, si el ensamblaje al que se hace referencia está en el GAC.

Considere un proyecto que hace referencia al ensamblaje A, que a su vez depende de los ensamblajes B y C. El ensamblaje C resulta haber sido instalado en el GAC por algún "otro producto". Descubrí que Visual Studio 2013 copia A y B, pero no C, a la carpeta de salida, porque C ya está en el GAC. Si luego ejecuto la aplicación en una máquina que no tiene "otro producto" instalado, obtengo una falla de enlace de tiempo de ejecución.

También he notado que la documentación de Microsoft en esta área parece estar equivocada, al menos para VS2013.

Managing Project References estados

Si implementa una aplicación que contiene una referencia a un componente personalizado que se registra en el GAC, el componente no serán desplegados con la aplicación, independientemente de la configuración CopyLocal. En versiones anteriores de Visual Studio, podía establecer la propiedad CopyLocal en una referencia para asegurarse de que se implementó el ensamblado. Ahora, debe agregar manualmente el conjunto a la carpeta \ Bin

Mis pruebas con espectáculo de VS2013 que, contrariamente a la, CopyLocal = True siempre copia el conjunto anterior hace referencia directamente a la carpeta de salida, independientemente de ya sea en el GAC. Pero los ensambles de referencia indirecta parecen copiarse solo si no están en el GAC.

Este comportamiento significa que para asegurarse de que los ensamblados de referencia indirecta se implementan con la aplicación, debe agregar referencias explícitas a ellos, con CopyLocal = True (o cópielos manualmente). Tenga en cuenta que, de manera predeterminada, CopyLocal se establecerá en False si el ensamblaje está en el GAC.

Cuestiones relacionadas