问题描述
|
我想使用.NET 4.0中的某些功能,但仍以Visual Studio 2010中的.NET 3.5为目标。基本上,我希望具有以下功能:
if (.NET 4 installed) then
execute .NET 4 feature
这是一项可选功能,如果系统已安装.NET 4.0,我希望它能够运行。如果系统仅具有.NET 3.5,则该功能将无法执行,因为它对应用程序来说不是至关重要的。
解决方法
首先,您必须以该框架的3.5版本为目标,但要使程序通过4.0框架可加载,使其具有如下所示的ѭ1((来自如何强制应用程序使用.NET 3.5或更高版本?):
<?xml version=\"1.0\" encoding=\"utf-8\" ?>
<configuration>
<startup>
<supportedRuntime version=\"v4.0\"/>
<supportedRuntime version=\"v2.0.50727\"/>
</startup>
</configuration>
至于激活4.0功能的方式,取决于您要使用的功能。如果它是内置类上的方法,则可以查找它并使用(如果存在)。这是C#中的一个示例(它同样适用于VB):
var textOptions = Type.GetType(\"System.Windows.Media.TextOptions,\" +
\"PresentationFramework,Version=4.0.0.0,\" +
\"Culture=neutral,PublicKeyToken=31bf3856ad364e35\");
if (textOptions != null)
{
var setMode = textOptions.GetMethod(\"SetTextFormattingMode\");
if (setMode != null)
// don\'t bother to lookup TextFormattingMode.Display -- we know it\'s 1
setMode.Invoke(null,new object[] { this,1 });
}
如果将其放在MainWindow
构造函数中,它将在.NET 4.0框架下运行的应用程序中将TextFormattingMode
设置为Display
,而在3.5下则不执行任何操作。
如果要使用3.5中没有的类型,则必须为其创建新的程序集。例如,使用以下代码创建一个针对4.0的类库项目\“ Factorial \”(您必须添加对System.Numerics的引用;相同的C#免责声明):
using System.Numerics;
namespace Factorial
{
public class BigFactorial
{
public static object Factorial(int arg)
{
BigInteger accum = 1; // BigInteger is in 4.0 only
while (arg > 0)
accum *= arg--;
return accum;
}
}
}
然后使用以下代码创建目标为3.5的项目(相同的C#免责声明):
using System;
using System.Reflection;
namespace runtime
{
class Program
{
static MethodInfo factorial;
static Program()
{ // look for Factorial.dll
try
{
factorial = Assembly.LoadFrom(\"Factorial.dll\")
.GetType(\"Factorial.BigFactorial\")
.GetMethod(\"Factorial\");
}
catch
{ // ignore errors; we just won\'t get this feature
}
}
static object Factorial(int arg)
{
// if the feature is needed and available,use it
if (arg > 20 && factorial != null)
return factorial.Invoke(null,new object[] { arg });
// default to regular behavior
long accum = 1;
while (arg > 0)
accum = checked(accum * arg--);
return accum;
}
static void Main(string[] args)
{
try
{
for (int i = 0; i < 25; i++)
Console.WriteLine(i + \": \" + Factorial(i));
}
catch (OverflowException)
{
if (Environment.Version.Major == 4)
Console.WriteLine(\"Factorial function couldn\'t be found\");
else
Console.WriteLine(\"You\'re running \" + Environment.Version);
}
}
}
}
如果将EXE和Factorial.DLL复制到同一目录中并运行它,则会在4.0下获得所有前25个阶乘,而最多只能得到20个阶乘以及3.5上的错误消息(或者可以)。找不到DLL)。
,不,你不能。一种有限的选择是使用条件编译,如下所示:
#if NET40
some 4.0 code
#else
some 3.5 code
#endif
但是这样做的局限性在于它要么在其中编译代码,要么不编译代码-您无法在运行时切换执行路径。 (条件编译符号可以在文件顶部或在项目属性“ build”选项卡中声明,也可以在编译项目时在命令行中声明(因此可以将其指定为自动生成的一部分))。
绝对最好的办法是确保安装.Net 4.0框架-完整版本只有49MB,因此它并不庞大。
,这里的主要问题是,您无法在.NET 4 CLR上运行针对.NET 3.5编译的代码,反之亦然。您需要再次为.NET4重新编译。
因此,您将拥有2个可执行文件,一个用于.NET 3.5,另一个用于.NET4。两者都具有相同的代码,但是您可以使用Preprocessor Directives(确切地说是#IF指令)来使这两个可执行文件有所区别。
然后在两个项目的配置中指定特定的指令。
,不可以,因为没有.NET 4 CLR,您将无法使用.NET 4功能。问题是程序集在加载时绑定,并且程序集绑定到您为其编译的CLR的特定版本。