一尘不染

条件编译和框架目标

c#

如果目标框架是较新的版本,则在一些较小的地方可以极大地改进我的项目代码。我希望能够更好地利用C#中的条件编译来根据需要切换这些条件。

就像是:

#if NET40
using FooXX = Foo40;
#elif NET35
using FooXX = Foo35;
#else NET20
using FooXX = Foo20;
#endif

这些符号中的任何一个免费吗?我是否需要在项目配置中注入这些符号?这样做似乎很容易,因为我将了解MSBuild所针对的框架。

/p:DefineConstants="NET40"

人们如何处理这种情况?您要创建其他配置吗?您是否通过命令行传递常量?


阅读 314

收藏
2020-05-19

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

此示例将在第一次构建后将Framework变量设置为NET20的情况下重新编译整个项目(同时编译并假定第一次构建是上述默认的NET35)。每个编译将具有正确设置的条件定义值。

通过这种方式,如果您希望不必#ifdef这些文件,甚至可以排除项目文件中的某些文件:

<Compile Include="SomeNet20SpecificClass.cs" Condition=" '$(Framework)' == 'NET20' " />

甚至参考

<Reference Include="Some.Assembly" Condition="" '$(Framework)' == 'NET20' " >
  <HintPath>..\Lib\$(Framework)\Some.Assembly.dll</HintPath>
</Reference>
2020-05-19