MSBuild: building of DefineConstants value

本文关键字:DefineConstants value of building MSBuild | 更新日期: 2024-11-08 02:21:36

我需要扩展我的csproj文件DefineConstants属性的当前值。我想添加为后缀的字符串可以在 C# 上计算,如下所示:

Int32 min_year = 2009;
Int32 max_year = 2015;      
String result = String.Join(";", Enumerable.Range(min_year, max_year -
  min_year + 1).Select(n=>"NEWER_THAN_AUTOCAD_" + (n - 1)).ToArray());
// result: 
// NEWER_THAN_AUTOCAD_2008;NEWER_THAN_AUTOCAD_2009;
// NEWER_THAN_AUTOCAD_2010;NEWER_THAN_AUTOCAD_2011;
// NEWER_THAN_AUTOCAD_2012;NEWER_THAN_AUTOCAD_2013;
// NEWER_THAN_AUTOCAD_2014

我需要在 MSBuild 代码中执行相同的逻辑...我尝试通过以下方式做到这一点:

$([System.String]::Join(`;`,[System.Linq.Enumerable]::Range(2009,[MSBuild]::Add(
[MSBuild]::Subtract($(CAD_Year),2009),1)).Select(n=>[System.String]::Concat(
"NEWER_THAN_AUTOCAD_"),[MSBuild]::Subtract(n,1).ToArray()))

但是我在 DefineConstants 属性而不是计算值中得到这个表达式。我该如何解决它?

MSBuild: building of DefineConstants value

首先:数你的括号 :P 最后少了一个。(但这无关紧要)

其次:如果你想"执行"一些特殊功能,你必须每次都使用$(),而不仅仅是第一次。所以这是不正确的:

<PropertyGroup>
  <MyDefineConstants>$([System.String]::Join(';',[System.Linq.Enumerable]::Range(2009,2012)))</MyDefineConstants>
</PropertyGroup>

这是正确的

<PropertyGroup>
  <MyDefineConstants>$([System.String]::Join(';',$([System.Linq.Enumerable]::Range(2009,2012))))</MyDefineConstants>
</PropertyGroup>

但。。。命名空间 System.Linq.Enumerable 在 MsBuld 中不可用。不能使用所需的每个命名空间。这是出于安全原因。如果你真的想使用它,你必须设置环境变量MSBUILDENABLEALLPROPERTYFUNCTIONS=1。但我不建议这样做。

如果您想了解更多信息:在Visual Studio博客上尝试MSBuild属性函数


除此之外:Select方法不是真正的方法。好的,是的,但不是您通常通过编写myobject.method()调用的那种。这是扩展方法。

这只是句法糖。当你编写Enumerable.Range(1, 5).Select(n => n*2)和编译器调用方法时,Enumerable.Select(Enumerable.Range(1, 5), n => n*2) - 这就是你应该如何调用它。


好了,咿咿呀...我认为最简单的方法是最好的...所以

<ItemGroup>
  <CadYear Include="2009" />
  <CadYear Include="2010" />
  <CadYear Include="2011" />
  <CadYear Include="2012" />
  <CadYear Include="2013" />
</ItemGroup>
<PropertyGroup>
  <DefineConstants>@(CadYear->'NEWER_THAN_AUTOCAD_%(Identity)')</DefineConstants>
</PropertyGroup>

你仍然需要设置年份,所以我认为如果你必须定义所有年份,这可能是一个缺点:P


或者......如果你真的找到了"干净"/"复杂"的解决方案。您只能编写内联任务。然后,您可以在 C# 中编写任何您想要的内容和任何复杂的代码。