条件编译和框架目标

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

就像是:

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

这些符号中的任何一个都是免费的吗? 我是否需要将这些符号作为项目配置的一部分注入? 似乎很容易做到,因为我知道哪个框架是MSBuild的目标。

 /p:DefineConstants="NET40" 

更新:我的问题是人们如何处理这种情况? 你在创造不同的配置吗? 您是否通过命令行传递常量?

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

  NET20 bin\$(Configuration)\$(Framework)   NET35 bin\$(Configuration)\$(Framework)  

在您的一个默认配置中:

 NET35 

如果没有在其他地方定义,则设置默认值。 在上面的例子中,每次构建每个版本时,OutputPath都会为您提供一个单独的程序集。

然后创建一个AfterBuild目标来编译不同的版本:

    

这个例子将在第一次构建之后将Framework变量设置为NET20重新编译整个项目(编译两者并假设第一个构建是上面的默认NET35)。 每个编译都将正确设置条件定义值。

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

  

甚至参考

  ..\Lib\$(Framework)\Some.Assembly.dll  

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

   $(DefineConstants);$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", "")) $(DefineConstants.Remove($(DefineConstants.LastIndexOf(";NET"))));$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))  

这取得了TargetFrameworkVersion属性的值,就像“v3.5”一样,取代了“v”和“。”。 得到“NET35”(使用新的属性函数function)。 然后删除任何现有的“NETxx”值并将其添加到DefinedConstants的末尾。 有可能简化这一点,但我没有时间来摆弄。

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

请注意,这似乎并没有给出客户端配置文件目标选项的任何不同,但这对我来说不是问题。

我遇到了这些解决方案的问题,可能是因为我的初始常量是由这些属性预先构建的。

  true true true 

Visual Studio 2010也因为冒​​号而引发错误,声称它们是非法字符。 错误信息给了我一个提示,因为我可以看到预制的常量用逗号分隔,最后是我的“非法”分号。 经过一些重新格式化和按摩后,我能够找到适合我的解决方案。

    $(DefineConstants)$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", "")),  $(DefineConstants.Remove($(DefineConstants.LastIndexOf(", NET"))))$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", "")),  $(DefineConstants)NET_20_OR_GREATER,  $(DefineConstants)NET_35_OR_GREATER $(DefineConstants.Remove($(DefineConstants.LastIndexOf(", "))))  

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

编辑:得到令人惊讶的快…谢谢你们! 这是截图:

高级编译器设置

首先清除常量:

    

接下来,构建调试,跟踪和其他常量,如:

  true full false TRACE;DEBUG;$(DefineConstants)  

最后,构建框架常量:

  NET10;NET20;$(DefineConstants)   NET10;NET20;NET30;$(DefineConstants)   NET10;NET20;NET30;NET35;$(DefineConstants)   NET10;NET20;NET30;NET35;NET40;$(DefineConstants)   NET10;NET20;NET30;NET35;NET40;NET45;$(DefineConstants)  

我认为这种方法非常易读且易于理解。

在.csproj文件中,在现有的DEBUG;TRACE行之后,添加以下内容:

 NET_40_OR_GREATER NET_40_EXACTLY 

为Debug和Release构建配置执行此操作。 然后在你的代码中使用:

 #if NET_40_OR_GREATER // can use dynamic, default and named parameters #endif 

@Azarien,你的答案可以与Jeremy’s合并,将它保存在一个地方而不是Debug | Release等。

对我来说,将两种变体结合起来效果最好,即使用#if NETXX在代码中包含条件,并且一次性构建不同的框架版本。

我在.csproj文件中有这些:

   NET_40_OR_GREATER   NET35 bin\$(Configuration)\$(TargetFrameworkVersion)  

在目标中: