MSBuild如何捕获ItemGroup定义时的属性原始值?
你在MSBuild脚本里先定义了RootNamespace的初始值为MyCustomNamespace,当TargetServer条件满足时,会把RootNamespace覆盖为MyServer.$(AssemblyName)。同时你通过ItemGroup设置了警告逻辑:当RootNamespace不等于MSBuildProjectName时输出警告,但当前警告输出的是修改后的RootNamespace值(比如MyServer.MyAssemblyName),而你希望捕获ItemGroup定义时的原始值MyCustomNamespace。已知MSBuild中属性求值早于项,下面给你解决办法。
你的原始代码示例:
<PropertyGroup> <RootNamespace>MyCustomNamespace</RootNamespace> </PropertyGroup> <!-- warn if not default --> <ItemGroup Condition="$(TargetServer) and '$(RootNamespace)' != '$(MSBuildProjectName)'"> <MyWarnings Include="RootNamespace would be overridden"> <Info>$(RootNamespace)</Info> <Code>MY0001</Code> </MyWarnings> </ItemGroup> <PropertyGroup Condition="$(TargetServer)"> <RootNamespace>MyServer.$(AssemblyName)</RootNamespace> </PropertyGroup> <Target Name="ShowMyWarnings" AfterTargets="AfterBuild" Condition="'@(MyWarnings)' != ''"> <Warning Text="@(MyWarnings) %(MyWarnings.Info)" Code="%(MyWarnings.Code)"/> </Target>
当前输出:
Warning MY0001 : RootNamespace would be overridden MyServer.MyAssemblyName
期望输出:
Warning MY0001 : RootNamespace would be overridden MyCustomNamespace
解决办法
核心思路是把初始的RootNamespace值保存到一个不会被覆盖的独立属性中,利用MSBuild属性的求值顺序,后续修改RootNamespace不会影响这个新属性的值。
修改后的完整代码:
<PropertyGroup> <RootNamespace>MyCustomNamespace</RootNamespace> <!-- 保存原始RootNamespace值到独立属性 --> <OriginalRootNamespace>$(RootNamespace)</OriginalRootNamespace> </PropertyGroup> <!-- warn if not default --> <ItemGroup Condition="$(TargetServer) and '$(RootNamespace)' != '$(MSBuildProjectName)'"> <MyWarnings Include="RootNamespace would be overridden"> <!-- 使用保存的原始值 --> <Info>$(OriginalRootNamespace)</Info> <Code>MY0001</Code> </MyWarnings> </ItemGroup> <PropertyGroup Condition="$(TargetServer)"> <RootNamespace>MyServer.$(AssemblyName)</RootNamespace> </PropertyGroup> <Target Name="ShowMyWarnings" AfterTargets="AfterBuild" Condition="'@(MyWarnings)' != ''"> <Warning Text="@(MyWarnings) %(MyWarnings.Info)" Code="%(MyWarnings.Code)"/> </Target>
说明
在初始RootNamespace赋值后,立即将其复制到OriginalRootNamespace属性中,这个新属性不会被后续的覆盖操作影响。ItemGroup中的警告逻辑使用OriginalRootNamespace代替RootNamespace,就能正确捕获到初始的MyCustomNamespace值,最终输出符合预期的警告信息。
内容的提问来源于stack exchange,提问作者OwnageIsMagic

