.net - what - declare attribute c#
¿Cuáles son las diferencias entre AssemblyVersion, AssemblyFileVersion y AssemblyInformationalVersion? (7)
Hay tres atributos de versión de ensamblaje. ¿Qué son las diferencias? ¿Está bien si uso AssemblyVersion
e ignoro el resto?
MSDN dice:
Especifica la versión del ensamblaje que se atribuye.
Indica a un compilador que use un número de versión específico para el recurso de versión de archivo Win32. No se requiere que la versión del archivo Win32 sea la misma que el número de versión del ensamblaje.
AssemblyInformationalVersion :
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 usar los atributos de ensamblaje?
Cuando se modifica la AssemblyVersion de un ensamblaje, si tiene un nombre seguro, los ensamblajes de referencia deben volver a compilarse, de lo contrario, ¡el ensamblaje no se carga! Si no tiene un nombre seguro, si no se agrega explícitamente al archivo de proyecto, no se copiará en el directorio de salida cuando se genere, por lo que puede perder ensamblajes dependientes, especialmente después de limpiar el directorio de salida.
La versión de ensamblajes en .NET puede ser una perspectiva confusa dado que actualmente hay al menos tres formas de especificar una versión para su ensamblaje.
Aquí están los tres principales atributos de montaje 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 menor , Compilación y Revisión .
El AssemblyFileVersion
está destinado a identificar de forma única una compilación del ensamblaje individual
Normalmente, configurará manualmente el Major y Minor AssemblyFileVersion para reflejar la versión del ensamblaje, luego incrementará la Compilación y / o Revisión cada vez que su sistema de compilación compile el ensamblaje. AssemblyFileVersion debe permitirle identificar de forma única una compilación del ensamblaje, de modo que pueda usarlo como punto de partida para depurar cualquier problema.
En mi proyecto actual, el servidor de compilación codifica el número de lista de cambios de nuestro repositorio de control de origen en las partes de compilación y revisión de AssemblyFileVersion. Esto nos permite asignar directamente desde un ensamblaje a su código fuente, para cualquier ensamblaje generado por el servidor de compilación (sin tener que usar etiquetas o ramas en el control de la fuente, o mantener manualmente los registros de las versiones publicadas).
Este número de versión se almacena en el recurso de versión de Win32 y se puede ver al ver las páginas de propiedades del Explorador de Windows para el ensamblaje.
El CLR no se preocupa ni examina la AssemblyFileVersion.
La AssemblyInformationalVersion
pretende representar la versión de todo su producto
La AssemblyInformationalVersion está pensada para permitir un versionado coherente de todo el producto, que puede consistir en muchos ensamblajes que se versionan de forma independiente, tal vez con diferentes políticas de versionamiento, y potencialmente desarrollados por equipos dispares.
“Por ejemplo, la versión 2.0 de un producto puede contener varios ensamblajes; uno de estos ensamblajes está marcado como versión 1.0 ya que es un nuevo ensamblaje que no se envió en la versión 1.0 del mismo producto. Por lo general, establece que las partes principales y secundarias de este número de versión representan la versión pública de su producto. Luego, incrementa las partes de compilación y revisión cada vez que empaqueta un producto completo con todos sus ensamblajes ". - Jeffrey Richter, [CLR a través de C # (Segunda edición)] pág. 57
A CLR no le importa ni examina la AssemblyInformationalVersion.
La AssemblyVersion
es la única versión que le importa a CLR (pero le importa toda la AssemblyVersion
)
El CLR utiliza la AssemblyVersion para enlazar a ensamblados con nombre seguro. Se almacena en la tabla de metadatos de manifiesto AssemblyDef del ensamblado construido y en la tabla AssemblyRef de cualquier ensamblado que lo haga referencia.
Esto es muy importante, porque significa que cuando hace referencia a un ensamblaje con un nombre seguro, está estrechamente vinculado a una Asamblea específica de ese ensamblaje. Toda la AssemblyVersion debe ser una coincidencia exacta para que el enlace tenga éxito. Por ejemplo, si hace referencia a la versión 1.0.0.0 de un ensamblaje con nombre seguro en el momento de la compilación, pero solo la versión 1.0.0.1 de ese ensamblaje está disponible en tiempo de ejecución, ¡el enlace fallará! (A continuación, tendrá que solucionar este problema utilizando la redirección de enlace de ensamblaje ).
Confusión sobre si toda la AssemblyVersion
tiene que coincidir. (Sí, lo hace).
Existe una pequeña confusión acerca de si la AssemblyVersion completa tiene que ser una coincidencia exacta para que se cargue un ensamblaje. Algunas personas tienen la falsa creencia de que solo las partes Mayor y Menor de la Versión de la Asamblea deben coincidir para que la vinculación tenga éxito. 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. Solo ejecuta este código de ejemplo .
En mi máquina, la segunda carga de ensamblaje falla, y las dos últimas líneas del registro de fusión dejan perfectamente en 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 es probablemente porque Microsoft originalmente tenía la intención de ser un poco más indulgente en esta coincidencia estricta de la versión completa de la AssemblyVersion, al hacer coincidir solo las partes de las versiones Major y Minor:
"Al cargar un ensamblaje, el CLR encontrará automáticamente la última versión de servicio instalada que coincida con la versión mayor / menor del ensamblaje que se solicita". - Jeffrey Richter, [CLR a través de C # (Segunda edición)] pág. 56
Este fue el comportamiento en la versión Beta 1 del CLR 1.0, sin embargo, esta característica se eliminó antes de la versión 1.0 y no ha logrado resurgir en .NET 2.0:
“Nota: acabo de describir cómo debes pensar en los números de versión. Desafortunadamente, el CLR no trata los números de versión de esta manera. [En .NET 2.0], el CLR trata un número de versión como un valor opaco, y si un conjunto depende de la versión 1.2.3.4 de otro conjunto, el CLR intenta cargar la versión 1.2.3.4 solamente (a menos que haya una redirección de enlaces en su lugar) ). Sin embargo, Microsoft tiene planes de cambiar el cargador de CLR en una versión futura para que cargue la última versión / compilación de una versión mayor / menor de un ensamblaje . Por ejemplo, en una versión futura del CLR, si el cargador está tratando de encontrar la versión 1.2.3.4 de un conjunto y existe la versión 1.2.5.0, el cargador selecciona automáticamente la última versión de servicio. Este será un cambio muy bienvenido para el cargador de CLR; por mi parte, no puedo esperar ". - Jeffrey Richter, [CLR a través de C # (Segunda edición)] p. 164 (énfasis mío)
Como este cambio aún no se ha implementado, creo que es seguro asumir que Microsoft había hecho un seguimiento de esta intención, y quizás sea demasiado tarde para cambiar esto ahora. Intenté buscar en la web para averiguar qué sucedió con estos planes, pero no pude encontrar ninguna respuesta. Todavía quería llegar al fondo de esto.
Así que le envié un correo electrónico a Jeff Richter y le pregunté directamente: pensé que si alguien sabía lo que sucedió, sería él.
Respondió en menos de 12 horas, 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 recoger la última versión y compilación disponibles de un ensamblaje, pero este comportamiento fue revertido antes de .NET 1.0 enviado. Más tarde se intentó revivir esto, pero no se logró antes de que se lanzara el CLR 2.0. Luego vino Silverlight, que tuvo prioridad para el equipo CLR, por lo que esta funcionalidad se retrasó aún más. Mientras tanto, la mayoría de las personas que se encontraban en los días de CLR 1.0 Beta 1 han seguido adelante, por lo que es poco probable que esto vea la luz del día, a pesar de todo el arduo trabajo que ya se había realizado.
El comportamiento actual, al parecer, está aquí para quedarse.
También vale la pena señalar en mi discusión con Jeff que AssemblyFileVersion solo se agregó después de la eliminación del mecanismo de "avance automático", ya que después de la versión 1.0 Beta 1, cualquier cambio en la AssemblyVersion fue un cambio importante para sus clientes. ningún lugar para almacenar de forma segura su número de compilación. AssemblyFileVersion es ese refugio seguro, ya que nunca es examinado automáticamente por el CLR. Tal vez sea más claro de esta 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 (rompiendo) y Construir / Revisión (no rompiendo) de AssemblyVersion.
El resultado final: piense detenidamente cuando cambie su AssemblyVersion
La moraleja es que si está enviando ensamblados a los que otros desarrolladores van a hacer referencia, debe ser extremadamente cuidadoso cuando cambie (y no cambie) la Versión de ensamblaje de esos ensamblajes. Cualquier cambio en AssemblyVersion significará que los desarrolladores de aplicaciones tendrán que volver a compilar contra la nueva versión (para actualizar esas entradas de AssemblyRef) o usar redireccionamientos de enlaces de ensamblaje para anular manualmente el enlace.
- No cambie la AssemblyVersion por una versión de servicio que esté diseñada para ser compatible con versiones anteriores.
- Cambie la AssemblyVersion por una versión que sepa que tiene cambios de última hora.
Simplemente eche un vistazo a los atributos de la 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 que contiene toda la información de servicio interesante (es la parte de Revisión de esta versión que le indica en qué Service Pack está), mientras que AssemblyVersion está arreglado en un antiguo 2.0.0.0 aburrido. ¡Cualquier cambio en la AssemblyVersion obligaría a cada aplicación .NET que hace referencia a mscorlib.dll a volver a compilar contra la nueva versión!
Para mantener esta pregunta actualizada, vale la pena resaltar que NuGet utiliza AssemblyInformationalVersion y refleja la versión del paquete que incluye cualquier sufijo previo al lanzamiento.
Por ejemplo, una AssemblyVersion de 1.0.3. * Empaquetada con asp.net core dotnet-cli
dotnet pack --version-suffix ci-7 src/MyProject
Produce un paquete con la versión 1.0.3-ci-7 que puede inspeccionar con reflexión utilizando:
CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);
Vale la pena señalar algunas otras cosas:
1) Como se muestra en el cuadro de diálogo Propiedades del Explorador de Windows para el archivo de ensamblaje generado, hay dos lugares llamados "Versión del archivo". El que se ve en el encabezado del cuadro de diálogo muestra la AssemblyVersion, no la AssemblyFileVersion.
En la sección Información de otra versión, hay otro elemento llamado "Versión del archivo". Aquí es donde puede ver lo que se ingresó como AssemblyFileVersion.
2) AssemblyFileVersion es solo texto plano. No tiene que cumplir con las restricciones del esquema de numeración que hace AssemblyVersion (<build> <65K, por ejemplo). Puede ser 3.2. <Release tag text>. <datetime>, si lo desea. Tu sistema de compilación tendrá que rellenar los tokens.
Por otra parte, no está sujeto a la sustitución de comodines que es AssemblyVersion. Si solo tiene un valor de "3.0.1. *" En AssemblyInfo.cs, eso es exactamente lo que se mostrará en el elemento Otra versión de información-> Versión de archivo.
3) Sin embargo, no sé el impacto sobre un instalador de usar algo distinto a los números de versión de archivo numérico.
AssemblyInformationalVersion
y AssemblyFileVersion
se muestran cuando ve la información de "Versión" en un archivo a través del Explorador de Windows al ver las propiedades del archivo. Estos atributos realmente se compilan en un recurso VERSION_INFO
creado por el compilador.
AssemblyInformationalVersion
es el valor de "Versión del producto". AssemblyFileVersion
es el valor de "Versión de archivo".
AssemblyVersion
es específico de los ensamblados .NET y el cargador de ensamblajes .NET lo utiliza para saber qué versión de un ensamblaje se debe cargar / enlazar en tiempo de ejecución.
De estos, el único que es absolutamente requerido por .NET es el atributo AssemblyVersion
. Desafortunadamente, también puede causar la mayoría de los problemas cuando cambia de manera indiscriminada, especialmente si tiene un nombre fuerte para sus ensamblajes.
AssemblyVersion
prácticamente permanece dentro de .NET, mientras que AssemblyFileVersion
es lo que Windows ve. Si va a las propiedades de un conjunto que se encuentra en un directorio y cambia a la pestaña de versión, AssemblyFileVersion
es lo que verá arriba. Si ordena los archivos por versión, esto es lo que usa Explorer.
La AssemblyInformationalVersion
asigna a la "Versión del producto" y está destinada a ser puramente "utilizada por el hombre".
AssemblyVersion
es sin duda el más importante, pero tampoco me saltearía AssemblyFileVersion
. Si no proporciona AssemblyInformationalVersion
, el compilador lo agrega por usted eliminando la parte "revisión" de su número de versión y dejando el major.minor.build
AsambleaVersión
Donde se verán otros ensamblajes que hagan referencia a su ensamblaje. ¡Si este número cambia, otros conjuntos deben actualizar sus referencias a su conjunto! Se requiere la AssemblyVersion
.
Yo uso el formato: major.minor . Esto resultaría en:
[assembly: AssemblyVersion("1.0")]
Asamblea de archivosVersión
Utilizado para la implementación. Puede aumentar este número para cada implementación. Es utilizado por los programas de configuración. Úselo para marcar ensamblajes que tienen la misma AssemblyVersion
, pero que se generan a partir de diferentes construcciones.
En Windows, se puede ver en las propiedades del archivo.
Si es posible, deje que sea generado por MSBuild. El AssemblyFileVersion es opcional. Si no se da, se usa la AssemblyVersion.
Utilizo el formato: major.minor.revision.build , donde uso la revisión para la etapa de desarrollo (Alpha, Beta, RC y RTM), paquetes de servicio y correcciones. Esto resultaría en:
[assembly: AssemblyFileVersion("1.0.3100.1242")]
AsambleaInformaciónVersión
La versión del producto del montaje. 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 ''.
El Análisis de Código se quejará al respecto (CA2243) - reportado a Microsoft (no corregido en VS2013).
La AssemblyInformationalVersion
es opcional. Si no se da, se usa AssemblyFileVersion.
Yo uso el formato: major.minor [revisión como cadena] . Esto resultaría en:
[assembly: AssemblyInformationalVersion("1.0 RC1")]