MSBuild:构建 DefineConstants 值
MSBuild: building of DefineConstants value
我注意扩展我的 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
属性 中得到这个表达式而不是计算值。我该如何解决?
首先:数一数你的括号 :P 最后少了一个。 (但这无关紧要)
其次:如果你想'execute'一些特殊的功能,你必须每次都使用$()
,而不仅仅是第一次。所以这是不正确的:
<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
或者...如果您真的找到了'clean'/'complex'解决方案。你可以写Inline Task。然后你可以用C#写任何你想写的和你能想到的复杂代码。
我注意扩展我的 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
属性 中得到这个表达式而不是计算值。我该如何解决?
首先:数一数你的括号 :P 最后少了一个。 (但这无关紧要)
其次:如果你想'execute'一些特殊的功能,你必须每次都使用$()
,而不仅仅是第一次。所以这是不正确的:
<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
或者...如果您真的找到了'clean'/'complex'解决方案。你可以写Inline Task。然后你可以用C#写任何你想写的和你能想到的复杂代码。