Copia de reglas de ensamblajes referenciados

¿Qué reglas sigue VS (msbuild?) Durante la compilación de la solución? ¿En qué casos copiará los ensamblajes referenciados indirectamente a la carpeta de salida y en cuáles no?

preguntado el 27 de agosto de 11 a las 14:08

4 Respuestas

Solo he experimentado un poco, y parece cualquier ensamblaje referenciado indirectamente que tenga un tipo referenciado directamente por código en otro ensamblaje se copiará. Si no hay nada en el código, no lo será. Aquí está mi escenario de muestra:

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

    var foo = new DirectAssembly.SampleClass();
    
  • DirectAssembly: biblioteca de clases 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 público sin parámetros

Como se describió anteriormente, 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 sigue siendo una referencia) y el código fallará en el momento de la ejecución.

No digo que estos sean todos las reglas, pero son al menos un comienzo ...

Respondido 27 ago 11, 20:08

+1 Si se hace referencia directa a tipos de otros ensamblajes, se copiarán. En ocasiones he tenido que hacer referencia explícita a tipos, que normalmente se cargarían dinámicamente, para que se implementen. - Tim Lloyd

¡Pero no deberíamos tener que hacer esto! - binks

@binki: Estoy de acuerdo en que es una molestia, y con NuGet en ASP.NET 5 es mucho mejor. Pero al menos saber lo que se necesita ayuda ... - Jon Skeet

Hay una sutileza que no se aborda en las respuestas anteriores, a saber, si el ensamblado 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. Resulta que el ensamblaje C ha sido instalado en el GAC por algún "otro producto". Descubrí que Visual Studio 2013 copia A y B, pero no C, en 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 un error de enlace en tiempo de ejecución.

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

Gestión de referencias de proyectos estados

Si implementa una aplicación que contiene una referencia a un componente personalizado que está registrado en la GAC, el componente no se implementará con la aplicación, independientemente de la configuración de 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 ensamblaje a la carpeta \ Bin

Mis pruebas con VS2013 muestran que, al contrario de lo anterior, CopyLocal = True Siempre hay copia el ensamblado al que se hace referencia directamente en la carpeta de salida, independientemente de si está en el GAC. Pero los ensamblados referenciados indirectamente parecen copiarse solo si no están en el GAC.

Este comportamiento significa que para asegurarse de que los ensamblados referenciados indirectamente se implementen con su aplicación, debe agregar referencias explícitas a ellos, con CopyLocal = True (o copiarlos manualmente). Tenga en cuenta que, de forma predeterminada, CopyLocal se establecerá en False si el ensamblado está en el GAC.

Respondido 17 Oct 14, 12:10

Debería copiar todas las referencias recursivas. Por ejemplo:

enter image description here

--- EDITAR ---

Las reglas (al menos en VS2010) parecen ser las siguientes:

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

Por lo tanto, si desea asegurarse de que se implemente el ensamblado necesario para la reflexión, haga referencia a él desde el proyecto raíz.

Dejando de lado las preocupaciones de reflexión, parece suficiente con agregar el conjunto mínimo de referencias en cada nivel de jerarquía del proyecto.

Respondido 28 ago 11, 00:08

y ¿qué pasa si elimina el uso del ensamblaje C (pero conserva la referencia) de B? No copiará el ensamblaje C. ¿Y qué pasa si se usa el ensamblaje C por reflexión? No copiará el ensamblaje C - Chico siberiano

@Idsa: Sí, eso es precisamente lo que estaba escribiendo también. - Jon Skeet

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

Mi experiencia es que copia todos los ensamblados a los que se hace referencia directamente, de forma recursiva, es decir, todo lo que se hace referencia directamente en su código y todo lo que estos también hacen referencia.

Todo lo que no se haga referencia en tiempo de compilación en su código no será referenciado. Por lo tanto, las referencias que solo se resolvieron en tiempo de ejecución no se copiarán. Esto se debe a que, aunque sepa exactamente a qué hace referencia, el copmpiler no lo sabe. Ya sea por reflexión o usando el activador para hacer referencia (como en las dos respuestas ya dadas) porque en el momento de la compilación, el tipo real de los objetos no se puede determinar.

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 se basa en las referencias codificadas en el tiempo de compilación.

Esta es una de las razones por las que algunas de las técnicas de inyección pueden funcionar, antes de que no sea necesario realizar la resolución de la referencia en el punto de compilación o incluso implementación.

Respondido 27 ago 11, 21:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.