Referencias de Proyectos Dependientes del Modo de Compilación

Una de las cosas que más me gustan de la plataforma .NET y del Visual Studio es la gestión de referencias a otras librerías o entre proyectos dentro de una misma solución. Y ni de que hablar que desde que vio a la luz la plataforma NuGet, el tema de gestión y distribución de estas librerías se ha convertido en todo un paseo por el campo, ya que no es necesario indicar que librerías tiene que tener instalado o descargado los desarrolladores, sino que la solución (apropiadamente configurada) se encargará de recuperar los archivos correspondientes durante la primera compilación de forma automática… toda una maravilla!

Sin embargo, y en particular, al trabajar con librerías de terceras partes o third party libraries que no estén disponibles a través de NuGet, existen diversas estrategias que ya se empleaban desde los principios de .NET. La que personal y profesionalmente considero la más apropiada es la de crear una carpeta Lib en la raíz del directorio que contiene al archivo de solución (.sln) e ir colocando allí los diferentes archivos dll que se van a emplear.

Referencias de Proyectos Dependientes del Modo de Compilación - File System

Ejemplo de un proyecto pequeño y sencillo en .NET con soporte para NuGet. Nótese la carpeta Lib en la raíz del directorio que contiene el archivo de solución (.sln).

La parte final sería agregar el contenido de la carpeta Lib a la solución (a través de las funcionalidades de Add solution’s folder y de Add existing item…) para poder gestionar estas referencias a través del repositorio de versiones que empleemos: TFS, GitHub, SVN, o cualquier otro.

Pero… ¿Qué pasa si la version de librería de terceros que necesitamos emplear debe ser diferente en tiempo de desarrollo que en tiempo de despliegue/producción? ¿Cómo se gestiona una referencia a dos archivos dll diferentes dentro de un mismo proyecto y solución?

En principio no se puede. La referencia es exclusive a un archivo dll y a una versión de éste en específico, lo cual plantea un inconveniente que la mayoría de las personas termina resolviendo a través de dudosas prácticas y aún peores estrategias. Otros directamente culpan al Visual Studio y alegan que en otros IDEs es fácil hacer algo como ésto.

El problema es que esta necesidad es tan poco común que pocas personas en una empresa saben como resolverlo, pero la verdad es que es muy fácil a través del Visual Studio y de MSBUILD.

Solución

Supongamos que necesitamos referenciar una lirabría llamada My.Special.Library en una version especifica cunado compilamos en DEBUG y en una versión diferente cuando compilamos en RELEASE. Los pasos serían los siguientes:

  1. Desde el sistema de archivos navegamos hasta el directorio de la solución, y buscamos el directorio especial Lib.
  2. Dentro de Lib creamos dos (2) nuevos directorios: Debug y Release.
  3. Colocamos en cada nuevo directorio la versión de la libraría de terceros (en nuestro ejemplo My.Special.Library) donde corresponda, tal que la versión que queremos para el modo DEBUG esté en el directorio Debug, y de igual manera para el caso del modo RELEASE.
  4. Es importante desde el Visual Studio crear dos (2) ‘Solution Folders’ dentro del ‘Solution Folder’ de Lib para mapear los directorios Debug y Release así como su contenido para poder gestionarlos a través de nuestro correspondiente sistema de gestión de versiones.
    Referencias de Proyectos Dependientes del Modo de Compilación - Lib
  5. Luego, desde el Visual Studio, seleccionamos el proyecto que queremos trabajar desde el ‘Solutio Explorer’.
  6. Hacemos right-click sobre el proyecto y elegimos la opción de ‘Unload project’.
  7. Una vez que el proyecto a sido descargado, hacemos nuevamente right-click y elegimos la opción de editar el archivo .csproj.
  8. Se nos mostrará el XML que conforma el MSBUILD del proyecto. Allí debemos buscar donde comienzan las inclusions de las referencias en el proyecto, lo cual es fácil de identificar porque son una sucesión de tags Reference.
  9. Debemos colocar la siguientes instrucciones (XML) justo antes del ItemGroup que contiene las referencias:
    <Choose>
        <When Condition="'$(Configuration)'=='Debug'">
          <ItemGroup>
            <Reference Include="My.Special.Library, Version=1.222.2033.0, Culture=neutral, PublicKeyToken=26e441566366f4ab">
               <SpecificVersion>False</SpecificVersion>
              <HintPath>..\Lib\Debug\My.Special.Library.dll</HintPath>
            </Reference>
          </ItemGroup>
        </When>
         <Otherwise>
          <ItemGroup>
            <Reference Include="My.Special.Library, Version=1.342.2035.0, Culture=neutral, PublicKeyToken=26e441566366f4ab">
              <SpecificVersion>False</SpecificVersion>
               <HintPath>..\Lib\Release\My.Special.Library.dll</HintPath>
            </Reference>
          </ItemGroup>
        </Otherwise>
    </Choose> 
    
  10. Salvamos el archivo .csproj.
  11. Hacemos de nuevo right-click sobre el proyecto desde el ‘Solution Explorer’ y ahora elegimos la opción de ‘Reload Project’. Si el Visual Studio nos pregunta para cerrar el archivo .csproj, le contestamos que si.

Y listo, ya tenemos configurado el proyecto para que considerere una versión u otra de la librería de terceros dependiendo del modo de compilación, sin tener que hacer nada más, todo de forma automática y transparente.

Lo más interesante de esta solución es que la referencia se actualiza automáticamente y sin interrupciones en el proyecto que la contenga cuando cambiamos de modos de compilación desde el Visual Studio. Así, si estamos en el modo DEBUG, se estará referenciando a la version 1.222.2033.0, pero si cambiamos a otro modo (digamos RELEASE) automáticamente y sin enterarnos se actualizará la referencia del proyecto para utilizer la version 1.342.2035.0.

Por otro lado, no es estrictamente necesario tener que realizar la selección de una versián u otra si estamos en modo DEBUG o no, ya que como Visual Studio y el compilador de C# soportan variables de compilación, podemos definir nuestras porpias variables y emplear éstas para determiner que libraría y versión referenciar en nuestros proyectos.

Espero que este truco les sea de utilidad.

Anuncios
Deja un comentario

1 comentario

  1. Buenas Noches:

    engo el siguiente problema:

    Estoy Desarrollando un Servicio WCF con el cual tengo que hacer el CRUD hasta ahi no hay problema, el problema se presenta es que no tengo acceso directo a la BD me han entregado un API y esta la agrego al proyecto WCF mediante una dll esto ya lo hago sin problema, pero cuando quiero instanciar los objetos que estan embebidos en esta dll al ejecutar

    Interface
    [OperationContract]
    [WebInvoke(Method = “GET”, ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped,
    UriTemplate = “Prueba”)]

    Persons Prueba();

    Metodo

    public Persons Prueba()
    {
    Persons P = new Persons();
    P.OnSave();
    return null;
    }

    Al invoar el servicio y el metodo me sale este error

    Error de servidor en la aplicación ‘/’.
    No se puede cargar el archivo o ensamblado ‘W32_ACEInterface-3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’ ni una de sus dependencias. El sistema no puede encontrar el archivo especificado.
    Descripción: Excepción no controlada al ejecutar la solicitud Web actual. Revise el seguimiento de la pila para obtener más información acerca del error y dónde se originó en el código.

    Detalles de la excepción: System.IO.FileNotFoundException: No se puede cargar el archivo o ensamblado ‘W32_ACEInterface-3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’ ni una de sus dependencias. El sistema no puede encontrar el archivo especificado
    Agradesco sus comentarios si han tenido este tipo de problemas y de que forma lo han solucionado.

    Mil Gracias

    CarlosH

    Responder

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s