¿Cuáles son las diferencias entre AssemblyVersion, AssemblyFileVersion y AssemblyInformationalVersion?
Hay tres atributos de versión de ensamblaje. ¿Cuáles son las diferencias? ¿Está bien si uso AssemblyVersion
e ignoro el resto?
MSDN dice:
Versión de ensamblaje :
Especifica la versión del ensamblado que se atribuye.
Versión de archivo de ensamblaje :
Indica a un compilador que utilice un número de versión específico para el recurso de versión del archivo Win32. No es necesario que la versión del archivo Win32 sea la misma que el número de versión del ensamblado.
Versión informativa de ensamblaje :
Define información de versión adicional para un manifiesto de ensamblado.
Este es un seguimiento de ¿Cuáles son las mejores prácticas para utilizar los atributos de ensamblaje?
Versión de ensamblaje
Dónde se verán otros ensamblajes que hacen referencia a su ensamblaje. Si este número cambia, otros ensamblajes deben actualizar sus referencias a su ensamblaje. Actualice esta versión solo si rompe la compatibilidad con versiones anteriores. ElAssemblyVersion
requiere.
Utilizo el formato: mayor.menor (y mayor para bases de código muy estables). Esto daría como resultado:
[assembly: AssemblyVersion("1.3")]
Si sigue estrictamente SemVer , esto significa que solo actualizará cuando haya cambios importantes , es decir, 1.0, 2.0, 3.0, etc.
Versión del archivo ensamblado
Se utiliza para implementación (como programas de instalación). Puede aumentar este número para cada implementación. Úselo para marcar ensamblajes que tienen el mismoAssemblyVersion
pero que se generan a partir de diferentes compilaciones y/o códigos.
En Windows, se puede ver en las propiedades del archivo.
La versión AssemblyFileVersion es opcional. Si no se proporciona, se utiliza la versión de ensamblaje.
Utilizo el formato: major.minor.patch.build , donde sigo SemVer para las primeras tres partes y uso el número de compilación del servidor de compilación para la última parte (0 para compilación local). Esto daría como resultado:
[assembly: AssemblyFileVersion("1.3.2.42")]
Tenga en cuenta que System.Version nombra estas partes como major.minor.build.revision
!
AsambleaInformativaVersión
La versión del producto del ensamblaje. Esta es la versión que usaría al hablar con los clientes o para mostrarla en su sitio web. Esta versión puede ser una cadena, como ' 1.0 Release Candidate '.
ElAssemblyInformationalVersion
es opcional. Si no se proporciona, se utiliza AssemblyFileVersion.
Yo uso el formato: major.minor[.patch] [revision as string] . Esto daría como resultado:
[assembly: AssemblyInformationalVersion("1.3 RC1")]
El control de versiones de ensamblados en .NET puede ser una perspectiva confusa dado que actualmente existen al menos tres formas de especificar una versión para su ensamblado.
Estos son los tres atributos principales del ensamblado relacionados con la versión:
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]
Por convención, las cuatro partes de la versión se denominan Versión principal , Versión secundaria , Compilación y Revisión .
El AssemblyFileVersion
objetivo es identificar de forma única una compilación del ensamblaje individual.
Por lo general, configurará manualmente la versión de archivo de ensamblaje mayor y menor para reflejar la versión del ensamblaje y luego incrementará la compilación y/o la revisión cada vez que su sistema de compilación compila el ensamblaje. AssemblyFileVersion debería permitirle identificar de forma única una compilación del ensamblaje, de modo que pueda utilizarlo como punto de partida para depurar cualquier problema.
En mi proyecto actual, tenemos el servidor de compilación que codifica el número de la lista de cambios de nuestro repositorio de control de fuente en las partes de compilación y revisión de AssemblyFileVersion. Esto nos permite mapear directamente desde un ensamblado a su código fuente, para cualquier ensamblado generado por el servidor de compilación (sin tener que usar etiquetas o ramas en el control de código fuente, ni mantener manualmente ningún registro de las versiones publicadas).
Este número de versión se almacena en el recurso de versión Win32 y se puede ver al visualizar las páginas de propiedades del Explorador de Windows para el ensamblado.
Al CLR no le importa ni examina el AssemblyFileVersion.
Está AssemblyInformationalVersion
destinado a representar la versión de todo su producto.
El objetivo de AssemblyInformationalVersion es permitir el control de versiones coherente de todo el producto, que puede consistir en muchos ensamblados con versiones independientes, tal vez con diferentes políticas de control de versiones, y potencialmente desarrollados por equipos dispares.
“Por ejemplo, la versión 2.0 de un producto puede contener varios ensamblados; Uno de estos ensamblajes está marcado como versión 1.0 ya que es un ensamblaje nuevo que no se envió en la versión 1.0 del mismo producto. Normalmente, configura las partes mayor y menor de este número de versión para representar la versión pública de su producto. Luego, incrementa las piezas de construcción y revisión cada vez que empaqueta un producto completo con todos sus ensamblajes”. — Jeffrey Richter, [CLR vía C# (segunda edición)] p. 57
Al CLR no le importa ni examina la versión informativa de la Asamblea.
Es AssemblyVersion
la única versión que le importa a CLR (pero le importa todo el archivo AssemblyVersion
).
CLR utiliza AssemblyVersion para vincularse a ensamblados con nombres fuertes. Se almacena en la tabla de metadatos del manifiesto AssemblyDef del ensamblado creado y en la tabla AssemblyRef de cualquier ensamblado que haga referencia a él.
Esto es muy importante, porque significa que cuando hace referencia a un ensamblado con nombre seguro, está estrechamente vinculado a una versión de ensamblaje específica de ese ensamblado. Toda la versión de ensamblaje debe coincidir exactamente para que el enlace se realice correctamente. Por ejemplo, si hace referencia a la versión 1.0.0.0 de un ensamblado con nombre seguro en el momento de la compilación, pero solo la versión 1.0.0.1 de ese ensamblado está disponible en el tiempo de ejecución, ¡la vinculación fallará! (Luego tendrás que solucionar este problema utilizando la redirección de enlace de ensamblaje ).
Confusión sobre si el conjunto AssemblyVersion
tiene que coincidir. (Sí, lo hace).
Existe un poco de confusión sobre si toda la versión del ensamblaje debe coincidir exactamente para que se cargue un ensamblaje. Algunas personas tienen la falsa creencia de que solo las partes mayor y menor de la versión Asamblea deben coincidir para que la vinculación se realice correctamente. Esta es una suposición sensata, sin embargo, en última instancia es incorrecta (a partir de .NET 3.5) y es trivial verificar esto para su versión de CLR. Simplemente ejecute este código de muestra .
En mi máquina, la segunda carga de ensamblaje falla y las dos últimas líneas del registro de fusión dejan perfectamente claro por qué:
.NET Framework Version: 2.0.50727.3521
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
Successfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
Assembly binding for failed:
System.IO.FileLoadException: Could not load file or assembly 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral,
PublicKeyToken=0b3305902db7183f' or one of its dependencies. The located assembly's manifest definition
does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f'
=== Pre-bind state information ===
LOG: User = Phoenix\Dani
LOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
(Fully-specified)
LOG: Appbase = [...]
LOG: Initial PrivatePath = NULL
Calling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
LOG: Attempting download of new URL [...].
WRN: Comparing the assembly name resulted in the mismatch: Revision Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
Creo que la fuente de esta confusión probablemente se debe a que Microsoft originalmente tenía la intención de ser un poco más indulgente con esta coincidencia estricta de la versión completa de Assembly, al hacer coincidir solo las partes de la versión principal y secundaria:
"Al cargar un ensamblaje, CLR encontrará automáticamente la última versión de servicio instalada que coincida con la versión principal/secundaria del ensamblaje que se solicita". — Jeffrey Richter, [CLR vía C# (segunda edición)] p. 56
Este fue el comportamiento en Beta 1 de 1.0 CLR; sin embargo, esta característica se eliminó antes de la versión 1.0 y no logró resurgir en .NET 2.0:
“Nota: acabo de describir cómo se deben pensar los números de versión. Desafortunadamente, CLR no trata los números de versión de esta manera. [En .NET 2.0], CLR trata un número de versión como un valor opaco y, si un ensamblado depende de la versión 1.2.3.4 de otro ensamblado, CLR intenta cargar solo la versión 1.2.3.4 (a menos que exista una redirección vinculante). ). Sin embargo, Microsoft tiene planes de cambiar el cargador de CLR en una versión futura para que cargue la última compilación/revisión para una versión mayor/menor determinada de un ensamblado . Por ejemplo, en una versión futura de CLR, si el cargador intenta encontrar la versión 1.2.3.4 de un ensamblado y existe la versión 1.2.5.0, el cargador seleccionará automáticamente la última versión de servicio. Este será un cambio muy bienvenido en el cargador de CLR; por mi parte, no puedo esperar”. — Jeffrey Richter, [CLR vía C# (segunda edición)] p. 164 (el énfasis es mío)
Como este cambio aún no se ha implementado, creo que es seguro asumir que Microsoft había dado marcha atrás en su intento y tal vez sea demasiado tarde para cambiarlo ahora. Intenté buscar en la web para saber qué pasó con estos planes, pero no pude encontrar ninguna respuesta. Todavía quería llegar al fondo del asunto.
Entonces le envié un correo electrónico a Jeff Richter y le pregunté directamente; pensé que si alguien sabía lo que pasó, sería él.
Respondió en un plazo de 12 horas, nada menos que un sábado por la mañana, y aclaró que el cargador .NET 1.0 Beta 1 implementó este mecanismo de "avance automático" para seleccionar la última compilación y revisión disponible de un ensamblado, pero este comportamiento era revertido antes de que se enviara .NET 1.0. Más tarde se intentó revivir esto, pero no llegó antes de que se lanzara CLR 2.0. Luego vino Silverlight, que tenía prioridad para el equipo de CLR, por lo que esta funcionalidad se retrasó aún más. Mientras tanto, la mayoría de las personas que existían en los días de CLR 1.0 Beta 1 han seguido adelante, por lo que es poco probable que esto vea la luz, a pesar de todo el arduo trabajo que ya se había puesto en ello.
El comportamiento actual, al parecer, llegó para quedarse.
También vale la pena señalar de mi discusión con Jeff que AssemblyFileVersion solo se agregó después de la eliminación del mecanismo de "avance automático", porque después de 1.0 Beta 1, cualquier cambio en AssemblyVersion era un cambio importante para sus clientes, entonces había ningún lugar para almacenar de forma segura su número de compilación. AssemblyFileVersion es ese refugio seguro, ya que CLR nunca lo examina automáticamente. Tal vez sea más claro de esa manera, tener dos números de versión separados, con significados separados, en lugar de tratar de hacer esa separación entre las partes Mayor/Menor (de última hora) y Construcción/Revisión (no de última hora) de la Versión de Ensamblaje.
El resultado final: piense detenidamente cuándo cambiará suAssemblyVersion
La moraleja es que si envía ensamblados a los que otros desarrolladores van a hacer referencia, debe tener mucho cuidado al cambiar (y no cambiar) la versión de ensamblaje de esos ensamblados. Cualquier cambio en AssemblyVersion significará que los desarrolladores de aplicaciones tendrán que volver a compilar con la nueva versión (para actualizar esas entradas de AssemblyRef) o utilizar redirecciones de enlace de ensamblado para anular manualmente el enlace.
- No cambie la versión de ensamblaje por una versión de servicio que esté destinada a ser compatible con versiones anteriores.
- Cambie la versión de ensamblaje por una versión que sepa que tiene cambios importantes.
Simplemente eche otro vistazo a los atributos de versión en mscorlib:
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]
Tenga en cuenta que es AssemblyFileVersion la que contiene toda la información de servicio interesante (es la parte de Revisión de esta versión la que le indica en qué Service Pack se encuentra), mientras que AssemblyVersion está fijada en un viejo y aburrido 2.0.0.0. Cualquier cambio en AssemblyVersion obligaría a todas las aplicaciones .NET que hagan referencia a mscorlib.dll a volver a compilarse con la nueva versión.
AssemblyVersion
prácticamente permanece interno a .NET, mientras que AssemblyFileVersion
es lo que ve Windows. Si va a las propiedades de un ensamblaje ubicado en un directorio y cambia a la pestaña de versión, esto AssemblyFileVersion
es lo que verá en la parte superior. Si ordena los archivos por versión, esto es lo que utiliza Explorer.
Se AssemblyInformationalVersion
asigna a la "Versión del producto" y está destinado a ser puramente "utilizado por humanos".
AssemblyVersion
es sin duda el más importante, pero tampoco lo omitiría AssemblyFileVersion
. Si no proporciona AssemblyInformationalVersion
, el compilador lo agrega eliminando la parte de "revisión" de su número de versión y dejando major.minor.build.
AssemblyInformationalVersion
y AssemblyFileVersion
se muestran cuando ve la información de "Versión" de un archivo a través del Explorador de Windows al ver las propiedades del archivo. Estos atributos en realidad se compilan en un VERSION_INFO
recurso creado por el compilador.
AssemblyInformationalVersion
es el valor "Versión del producto". AssemblyFileVersion
es el valor "Versión del archivo".
Es AssemblyVersion
específico de los ensamblados .NET y lo utiliza el cargador de ensamblados .NET para saber qué versión de un ensamblado cargar/vincular en tiempo de ejecución.
De estos, el único que .NET requiere absolutamente es el AssemblyVersion
atributo. Desafortunadamente, también puede causar la mayoría de los problemas cuando cambia indiscriminadamente, especialmente si es fuerte nombrando sus ensamblajes.
Para mantener esta pregunta actualizada, vale la pena resaltar que AssemblyInformationalVersion
NuGet utiliza y refleja la versión del paquete , incluido cualquier sufijo previo al lanzamiento.
Por ejemplo, una versión de ensamblaje de 1.0.3.* empaquetada con el núcleo de asp.net dotnet-cli
dotnet pack --version-suffix ci-7 src/MyProject
Produce un paquete con la versión 1.0.3-ci-7 que puedes inspeccionar con reflexión usando:
CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);