为了账号安全,请及时绑定邮箱和手机立即绑定

条件编译和框架目标

条件编译和框架目标

小唯快跑啊 2019-07-22 15:33:19
条件编译和框架目标如果目标框架是一个较新的版本,那么我的项目的代码可能会在一些次要的地方得到大幅度的改进。我希望能够更好地利用C#中的条件编译来根据需要切换它们。类似于:#if NET40using FooXX = Foo40;#elif NET35using FooXX = Foo35;#else NET20using FooXX = Foo20;#endif这些符号中有免费的吗?是否需要将这些符号作为项目配置的一部分注入?似乎很容易做到,因为我将知道哪个框架是针对MSBuild的。/p:DefineConstants="NET40"最新情况:我的问题是,人们是如何处理这种情况的?您正在创建不同的配置吗?您是否通过命令行传入常量?
查看完整描述

3 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

实现这一目标的最佳方法之一是在项目中创建不同的构建配置:

<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>

此示例将在第一次构建后将Framework变量设置为NET 20重新编译整个项目(编译两者,并假设第一个构建是上面所述的默认NET 35)。每个编译都将正确设置条件定义值。

通过这种方式,您甚至可以将项目文件中的某些文件排除在外,如果您希望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>


查看完整回答
反对 回复 2019-07-22
?
慕沐林林

TA贡献2016条经验 获得超9个赞

到目前为止,我使用的另一种方法是将以下内容添加到项目文件中:

 <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”和“。获得“NET 35”(使用新的属性函数特征)。然后删除任何现有的“NETxx”值,并将其添加到DefinedConstants的末尾。这也许是可能的精简,但我没有时间去小提琴。

在VS中查看项目属性的Build选项卡,您将在条件编译符号部分看到结果值。更改应用程序选项卡上的目标框架版本,然后自动更改符号。然后你可以用#if NETxx预处理指令以通常的方式。在VS中更改项目似乎不会丢失自定义PropertyGroup。

请注意,这并没有为客户端配置文件目标选项提供任何不同的选项,但这对我来说不是一个问题。


查看完整回答
反对 回复 2019-07-22
?
慕后森

TA贡献1802条经验 获得超5个赞

我对这些解有问题,可能是因为我的初始常数是由这些属性预先建立的。

<DefineConstants /><DefineDebug>true</DefineDebug><DefineTrace>true</DefineTrace><DebugSymbols>true</DebugSymbols>

VisualStudio 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>

我会发布高级编译器设置对话框的屏幕截图(单击“高级编译选项.”打开)。按钮在项目的“编译”选项卡上)。但作为一个新用户,我缺乏这样做的代表。如果你能看到截图,你会看到自定义常量自动填充的属性组,然后你会说,“我要给我一些。”



查看完整回答
反对 回复 2019-07-22
  • 3 回答
  • 0 关注
  • 555 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信