我可以在面向.NET 3.5 SP1时使用.NET 4功能吗?

时间:2011-05-25 04:40:57

标签: .net vb.net visual-studio-2010 .net-3.5 .net-4.0

我想使用.NET 4.0中的一些功能,但仍然在Visual Studio 2010中使用.NET 3.5。基本上我希望有类似的东西:

if (.NET 4 installed) then
    execute .NET 4 feature

这是一个可选功能,如果系统安装了.NET 4.0,我希望它能够运行。如果系统只有.NET 3.5,则该功能将不会执行,因为它不是对应用程序至关重要的功能。

4 个答案:

答案 0 :(得分:9)

首先,您必须定位3.5版本的框架,但是通过App.config看起来像这样(来自How to force an application to use .NET 3.5 or above?),可以通过4.0框架加载程序:

<?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中不可用的类型,则必须为其创建新的程序集。例如,创建一个名为“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。

答案 1 :(得分:3)

不,你不能。一个有限的选择是使用条件编译,如下所示:

#if NET40
    some 4.0 code 
#else
    some 3.5 code
#endif

但是它的局限性在于它要么编译代码还是不编译代码 - 您无法在运行时切换执行路径。 (conditional compilation symbols可以在文件顶部或项目属性构建选项卡中声明,也可以在编译项目时在命令行上声明(因此可以将它们指定为自动构建的一部分)。 / p>

绝对最好的办法是确保安装.Net 4.0框架 - 完整版只有49MB,所以它不是很大。

答案 2 :(得分:1)

这里的主要问题是,您无法在.NET 4 CLR上运行为.NET 3.5编译的代码,反之亦然。您需要再次为.NET4重新编译。

因此,您将拥有2个可执行文件,一个用于.NET 3.5,第二个用于.NET 4.两者将具有相同的代码,但您可以使用Preprocessor Directives,具体地#IF指令,来区分这两者。

然后在两个项目的配置中指定特定指令。

答案 3 :(得分:0)

不,因为没有.NET 4 CLR就无法使用.NET 4功能。问题是程序集在加载时绑定,并且程序集绑定到您编译的CLR的特定版本。