有几个小的地方,我的项目的代码可能是能够显着改善,如果目标框架是一个新的版本。 我希望能够更好地利用条件编译在C#中切换这些需要。
就像是:
#if NET40
using FooXX = Foo40;
#elif NET35
using FooXX = Foo35;
#else NET20
using FooXX = Foo20;
#endif
做任何这些符号来进行免费的吗? 我需要注入这些符号作为项目配置的一部分? 似乎很容易做到,因为我知道哪些框架正在从MSBuild的针对性。
/p:DefineConstants="NET40"
更新:我的问题是如何被人处理这种情况? 你创建不同的配置? 你在常量通过命令行传递?
Answer 1:
其中一个做到这一点的最好办法是在项目中创建不同的生成配置:
<PropertyGroup Condition=" '$(Framework)' == 'NET20' ">
<DefineConstants>NET20</DefineConstants>
<OutputPath>bin\$(Configuration)\$(Framework)</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Framework)' == 'NET35' ">
<DefineConstants>NET35</DefineConstants>
<OutputPath>bin\$(Configuration)\$(Framework)</OutputPath>
</PropertyGroup>
而在默认配置中的一种:
<Framework Condition=" '$(Framework)' == '' ">NET35</Framework>
这将设置默认值,如果没有定义任何其他地方。 在上述情况下,OutputPath将每次构建每个版本的时间给你一个单独的程序集。
然后创建一个AfterBuild目标编译不同的版本:
<Target Name="AfterBuild">
<MSBuild Condition=" '$(Framework)' != 'NET20'"
Projects="$(MSBuildProjectFile)"
Properties="Framework=NET20"
RunEachTargetSeparately="true" />
</Target>
这个例子将重新编译与第一版本(编译两者并假设第一个构建是从上面的默认NET35)后设定为NET20框架变量整个项目。 每个编译都会有正确设置条件定义值。
通过这种方式,你甚至可以排除某些文件在项目文件中,如果你想W / O不必在支持#ifdef文件:
<Compile Include="SomeNet20SpecificClass.cs" Condition=" '$(Framework)' == 'NET20' " />
甚至引用
<Reference Include="Some.Assembly" Condition="" '$(Framework)' == 'NET20' " >
<HintPath>..\Lib\$(Framework)\Some.Assembly.dll</HintPath>
</Reference>
Answer 2:
这是为我工作至今的替代方法是添加以下的项目文件:
<PropertyGroup>
<DefineConstants Condition=" !$(DefineConstants.Contains(';NET')) ">$(DefineConstants);$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</DefineConstants>
<DefineConstants Condition=" $(DefineConstants.Contains(';NET')) ">$(DefineConstants.Remove($(DefineConstants.LastIndexOf(";NET"))));$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</DefineConstants>
</PropertyGroup>
这需要TargetFrameworkVersion属性,它是像“V3.5”的值,取代了“V”和“” 得到“NET35”(使用新的属性函数功能)。 然后删除任何现有的“NETxx”值,并将其添加到DefinedConstants结束。 它可能会简化这一点,但我没有摆弄的时间。
展望项目属性在VS,你会看到在条件编译符号部分所产生的价值的生成选项卡上。 更改应用程序选项卡上的目标框架版本,然后自动改变符号。 然后,您可以使用#if NETxx
以通常的方式预处理指令。 改变VS项目似乎并没有失去自定义的PropertyGroup。
请注意,这并没有给似乎给你任何的客户端配置文件选择目标不同,但是这不是我的问题。
Answer 3:
我曾与这些解决方案的问题,可能是因为我最初的常数通过这些属性预建。
<DefineConstants />
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<DebugSymbols>true</DebugSymbols>
Visual Studio 2010中也扔了一个错误,因为分号,声称他们是非法字符。 该错误消息给了我一个提示,我可以看到由逗号,最终其次是我的“非法”分号分隔的预建的常量。 一些格式化和按摩后,我能想出这对我工作的解决方案。
<PropertyGroup>
<!-- Adding a custom constant will auto-magically append a comma and space to the pre-built constants. -->
<!-- Move the comma delimiter to the end of each constant and remove the trailing comma when we're done. -->
<DefineConstants Condition=" !$(DefineConstants.Contains(', NET')) ">$(DefineConstants)$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", "")), </DefineConstants>
<DefineConstants Condition=" $(DefineConstants.Contains(', NET')) ">$(DefineConstants.Remove($(DefineConstants.LastIndexOf(", NET"))))$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", "")), </DefineConstants>
<DefineConstants Condition=" $(TargetFrameworkVersion.Replace('v', '')) >= 2.0 ">$(DefineConstants)NET_20_OR_GREATER, </DefineConstants>
<DefineConstants Condition=" $(TargetFrameworkVersion.Replace('v', '')) >= 3.5 ">$(DefineConstants)NET_35_OR_GREATER</DefineConstants>
<DefineConstants Condition=" $(DefineConstants.EndsWith(', ')) ">$(DefineConstants.Remove($(DefineConstants.LastIndexOf(", "))))</DefineConstants>
</PropertyGroup>
我会发布高级编译器设置对话框的截图(点击你的项目的编译选项卡上的“高级编译选项...”按钮打开)。 但作为一个新的用户,我缺乏代表这样做。 如果你能看到的截图,你会看到自定义常量由地产集团自动填充,然后你会说,“我得给我一些这一点。”
编辑:明白了代表出奇的快..谢谢你们! 下面是截图:
Answer 4:
与清除常量开始:
<PropertyGroup>
<DefineConstants/>
</PropertyGroup>
其次,建立你的调试,跟踪等常量,如:
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>TRACE;DEBUG;$(DefineConstants)</DefineConstants>
</PropertyGroup>
最后,建立自己的框架常量:
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v2.0' ">
<DefineConstants>NET10;NET20;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v3.0' ">
<DefineConstants>NET10;NET20;NET30;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v3.5' ">
<DefineConstants>NET10;NET20;NET30;NET35;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v4.0' ">
<DefineConstants>NET10;NET20;NET30;NET35;NET40;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v4.5' ">
<DefineConstants>NET10;NET20;NET30;NET35;NET40;NET45;$(DefineConstants)</DefineConstants>
</PropertyGroup>
我觉得这种做法是非常易于阅读和理解。
Answer 5:
在一个.csproj的文件,现有的后<DefineConstants>DEBUG;TRACE</DefineConstants>
线,补充一点:
<DefineConstants Condition=" '$(TargetFrameworkVersion.Replace("v",""))' >= '4.0' ">NET_40_OR_GREATER</DefineConstants>
<DefineConstants Condition=" '$(TargetFrameworkVersion.Replace("v",""))' == '4.0' ">NET_40_EXACTLY</DefineConstants>
这样做对Debug和Release生成配置。 然后在代码中使用:
#if NET_40_OR_GREATER
// can use dynamic, default and named parameters
#endif
Answer 6:
@Azarien,你的答案可以与Jeremy的组合使其保持在一个地方,而不是调试|发布等
对我来说,结合两种变化的效果最好,即包括使用#如果NETXX代码条件,并且一气呵成建设不同framework版本。
我有这些在我的.csproj文件:
<PropertyGroup>
<DefineConstants Condition=" '$(TargetFrameworkVersion.Replace("v",""))' >= '4.0' ">NET_40_OR_GREATER</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFrameworkVersion.Replace("v",""))' == '3.5' ">
<DefineConstants>NET35</DefineConstants>
<OutputPath>bin\$(Configuration)\$(TargetFrameworkVersion)</OutputPath>
</PropertyGroup>
和目标:
<Target Name="AfterBuild">
<MSBuild Condition=" '$(TargetFrameworkVersion.Replace("v",""))' >= '4.0' "
Projects="$(MSBuildProjectFile)"
Properties="TargetFrameworkVersion=v3.5"
RunEachTargetSeparately="true" />
</Target>
文章来源: Conditional Compilation and Framework Targets