MSBuild:构建DefineConstants值

时间:2015-03-10 11:50:49

标签: c# visual-studio msbuild

我注意扩展我的DefineConstants文件的csproj属性的当前值。我想要添加为后缀的字符串可以在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属性中得到了这个表达式而不是求值。我该如何解决?

1 个答案:

答案 0 :(得分:3)

首先:计算括号:P最后有一个丢失。 (但这是无关紧要的)

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

<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。但我不推荐这个。

如果您想了解更多信息:try MSBuild Property Functions on The Visual Studio Blog


除了上述内容:Select方法不是真正的方法。好吧,它是,但不是那种你通常通过写myobject.method()来调用的。这是Extension Methods

这只是语法糖。当你编写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


或者......如果你真的找到&#39; clean&#39; /&#39;复杂&#39;解。你可以写Inline Task。然后,您可以编写您想要的内容以及您在C#中可以想到的复杂代码。