Comparar propiedades y elementos
Las propiedades y los elementos de MSBuild se usan para pasar información a tareas, evaluar condiciones y almacenar valores a los que se puede hacer referencia en el archivo del proyecto.
Las propiedades son pares de nombre y valor.Para obtener más información, vea Propiedades de MSBuild.
Los elementos son objetos que normalmente representan archivos.Los objetos de elemento pueden tener asociadas colecciones de metadatos.Los metadatos son pares de nombre y valor.Para obtener más información, vea Elementos de MSBuild.
Escalares y vectores
Dado que las propiedades de MSBuild son pares de nombre y valor que tienen simplemente un valor de cadena, se suelen describir como escalares.Dado que los tipos de elemento de MSBuild son listas de elementos, se suelen describir como vectores.Sin embargo, en la práctica, las propiedades pueden representar varios valores y los tipos de elemento pueden tener cero elementos o un elemento.
Inyección de dependencia de destino
Para ver cómo las propiedades pueden representar varios valores, considere un modelo de uso común para agregar un destino a una lista de destinos que se va a compilar.Normalmente, esta lista está representada por un valor de propiedad, con los nombres de destino separados por puntos y coma.
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
La propiedad BuildDependsOn se utiliza normalmente como argumento de un atributo DependsOnTargets de destino, convirtiéndolo de hecho en una lista de elementos.Esta propiedad se puede invalidar para agregar un destino o para cambiar el orden de ejecución de destinos.Por ejemplo,
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
CustomBuild;
</BuildDependsOn>
</PropertyGroup>
agrega el destino CustomBuild a la lista de destinos, dando a BuildDependsOn el valor BeforeBuild;CoreBuild;AfterBuild;CustomBuild.
A partir de MSBuild 4.0, la inyección de dependencia de destino es un concepto desusado.En su lugar, utilice los atributos AfterTargets y BeforeTargets.Para obtener más información, vea Orden de compilación de destinos.
Conversiones entre cadenas y listas de elementos
MSBuild realiza conversiones a y de tipos de elemento y valores de cadena, según sea necesario.Para ver cómo una lista de elementos se puede convertir en un valor de cadena, considere lo que sucede cuando un tipo de elemento se utiliza como valor de una propiedad de MSBuild:
<ItemGroup>
<OutputDir Include="KeyFiles\;Certificates\" />
</ItemGroup>
<PropertyGroup>
<OutputDirList>@(OutputDir)</OutputDirList>
</PropertyGroup>
El tipo de elemento OutputDir tiene un atributo Include con el valor "KeyFiles\;Certificates\".MSBuild analiza esta cadena en dos elementos: KeyFiles\ y Certificates\.Cuando el tipo de elemento OutputDir se utiliza como valor de la propiedad OutputDirList, MSBuild convierte o "condensa" el tipo de elemento en la cadena separada por punto y coma "KeyFiles\;Certificates\".
Propiedades y elementos en tareas
Las propiedades y los elementos se utilizan como entradas y salidas en MSBuild.Para obtener más información, vea Tareas de MSBuild.
Las propiedades se pasan a las tareas como atributos.Dentro de la tarea, una propiedad de MSBuild está representada por un tipo de propiedad cuyo valor se puede convertir a y de una cadena.Entre los tipos de propiedad admitidos se incluyen bool, char, DateTime, Decimal, Double, int, string y cualquier tipo que ChangeType pueda administrar.
Los elementos se pasan a las tareas como objetos ITaskItem.Dentro de la tarea, ItemSpec representa el valor del elemento y GetMetadata recupera sus metadatos.
La lista de elementos de un tipo de elemento se puede pasar como una matriz de objetos ITaskItem.A partir de .NET Framework 3.5, los elementos se pueden quitar de una lista de elementos en un destino utilizando el atributo Remove.Dado que se pueden quitar elementos de una lista de elementos, es posible que un tipo de elemento no tenga elementos.Si una lista de elementos se pasa a una tarea, el código en la tarea debe comprobar esta posibilidad.
Orden de evaluación de propiedades y elementos
Durante la fase de evaluación de una compilación, los archivos importados se incorporan a la compilación en el orden en que aparecen.Las propiedades y los elementos se definen en tres pasos en el orden siguiente:
Las propiedades se definen y modifican en el orden en que aparecen.
Las definiciones de elementos se definen y modifican en el orden en que aparecen.
Los elementos se definen y modifican en el orden en que aparecen.
Durante la fase de ejecución de una compilación, las propiedades y los elementos que se definen dentro de los destinos se evalúan conjuntamente en una sola fase en el orden en que aparecen.
Sin embargo, esto no es todo.Cuando se define una propiedad, una definición de elemento o un elemento, se evalúa su valor.El evaluador de expresiones expande la cadena que especifica el valor.La expansión de la cadena depende de la fase de compilación.Este es un orden de evaluación de propiedades y elementos más detallado:
Durante la fase de evaluación de una compilación:
Las propiedades se definen y modifican en el orden en que aparecen.Las funciones de propiedad se ejecutan.Los valores de propiedad con la forma $(nombreDePropiedad) se expanden dentro de las expresiones.El valor de propiedad se establece en la expresión expandida.
Las definiciones de elementos se definen y modifican en el orden en que aparecen.Las funciones de propiedad ya se han expandido dentro de las expresiones.Los valores de metadatos se establecen en las expresiones expandidas.
Los tipos de elemento se definen y modifican en el orden en que aparecen.Los valores de elemento con la forma @(tipoDeElemento) se expanden.Las transformaciones de elemento también se expanden.Las funciones y los valores de propiedad ya se han expandido dentro de las expresiones.Los valores de metadatos y lista de elementos se establecen en las expresiones expandidas.
Durante la fase de ejecución de una compilación:
- Las propiedades y los elementos definidos dentro de los destinos se evalúan conjuntamente en el orden en que aparecen.Las funciones de propiedad se ejecutan y los valores de propiedad se expanden dentro de las expresiones.Los valores de elemento y las transformaciones de elemento también se expanden.Los valores de propiedad, los valores de tipo de elemento y los valores de metadatos se establecen en las expresiones expandidas.
Efectos sutiles del orden de evaluación
En la fase de evaluación de una compilación, la evaluación de propiedades precede a la evaluación de elementos.No obstante, las propiedades pueden tener valores que parezcan depender de valores de elementos.Considere el script siguiente.
<ItemGroup>
<KeyFile Include="KeyFile.cs">
<Version>1.0.0.3</Version>
</KeyFile>
</ItemGroup>
<PropertyGroup>
<KeyFileVersion>@(KeyFile->'%(Version)')</KeyFileVersion>
</PropertyGroup>
<Target Name="AfterBuild">
<Message Text="KeyFileVersion: $(KeyFileVersion)" />
</Target>
Al ejecutar la tarea Message, se muestra este mensaje:
KeyFileVersion: 1.0.0.3
Esto se debe a que el valor de KeyFileVersion es realmente la cadena "@(KeyFile->'%(Version)')".El elemento y las transformaciones de elemento no se expandieron cuando la propiedad se definió por primera vez, por lo que a la propiedad KeyFileVersion se le asignó el valor de la cadena sin expandir.
Durante la fase de ejecución de la compilación, cuando procesa la tarea Message, MSBuild expande la cadena "@(KeyFile->'%(Version)')" para producir "1.0.0.3".
Observe que aparecería el mismo mensaje aunque se invirtiera el orden de los grupos de propiedades y elementos.
Como un segundo ejemplo, considere lo que puede suceder cuando los grupos de propiedades y elementos se encuentran dentro de los destinos:
<Target Name="AfterBuild">
<PropertyGroup>
<KeyFileVersion>@(KeyFile->'%(Version)')</KeyFileVersion>
</PropertyGroup>
<ItemGroup>
<KeyFile Include="KeyFile.cs">
<Version>1.0.0.3</Version>
</KeyFile>
</ItemGroup>
<Message Text="KeyFileVersion: $(KeyFileVersion)" />
</Target>
La tarea Message muestra este mensaje:
KeyFileVersion:
Esto se debe a que durante la fase de ejecución de la compilación, los grupos de propiedades y elementos definidos dentro de los destinos se evalúan de arriba abajo al mismo tiempo.Cuando se define KeyFileVersion, KeyFile no se conoce.Por consiguiente, la transformación de elemento se expande a una cadena vacía.
En este caso, la inversión del orden de los grupos de propiedades y elementos restaura el mensaje original:
<Target Name="AfterBuild">
<ItemGroup>
<KeyFile Include="KeyFile.cs">
<Version>1.0.0.3</Version>
</KeyFile>
</ItemGroup>
<PropertyGroup>
<KeyFileVersion>@(KeyFile->'%(Version)')</KeyFileVersion>
</PropertyGroup>
<Message Text="KeyFileVersion: $(KeyFileVersion)" />
</Target>
El valor de KeyFileVersion se establece en "1.0.0.3" y no en "@(KeyFile->'%(Version)')".La tarea Message muestra este mensaje:
KeyFileVersion: 1.0.0.3