条件编译和框架目标
如果目标框架是较新的版本,那么我的项目代码可能会有一些小的地方可以大大改进。 我希望能够更好地利用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文件中,在现有的
行之后,添加以下内容:
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)
在目标中: