在定位.NET 3.5 SP1时可以使用.NET 4功能吗?

问题描述

| 我想使用.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的特定版本。