Можно ли использовать функцию .NET 4 для таргетинга на .NET 3.5 SP1? - PullRequest
5 голосов
/ 25 мая 2011

Я хотел бы использовать некоторые функции в .NET 4.0, но все еще нацеливаться на .NET 3.5 в Visual Studio 2010. По сути, я хочу иметь что-то вроде:

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

Это дополнительная функция, и мне бы хотелось, чтобы она работала, если в системе установлен .NET 4.0. Если в системе установлен только .NET 3.5, эта функция не будет работать, поскольку она не является критически важной для приложения.

Ответы [ 4 ]

9 голосов
/ 26 мая 2011

Прежде всего, вам нужно настроить таргетинг на версию 3.5 фреймворка, но сделать вашу программу загружаемой с помощью фреймворка 4.0, имея App.config, который выглядит следующим образом (из Как заставить приложение использовать .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 конструктор, он установит TextFormattingMode в Display в приложениях, работающих в среде .NET 4.0, и ничего не сделает в 3.5.

Если вы хотите использовать тип, который недоступен в 3.5, вы должны создать для него новую сборку. Например, создайте проект библиотеки классов с целью «4.0» под названием «Факториал» с таким кодом (вам необходимо добавить ссылку на 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 в один и тот же каталог и запустите его, вы получите все первые 25 факториалов под 4.0 и только факториалы до 20 вместе с сообщением об ошибке 3.5 (или, если это возможно) не могу найти DLL).

3 голосов
/ 25 мая 2011

Нет, ты не можешь. Одним из ограниченных вариантов является использование условной компиляции, например:

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

но ограничением этого является то, что он либо компилирует код, либо нет - вы не можете переключать путь выполнения во время выполнения. (Символы условной компиляции могут быть объявлены либо в верхней части файла, либо на вкладке сборки свойств проекта, либо в командной строке при компиляции проекта (поэтому их можно указать как часть автоматической сборки). )).

Абсолютно лучшее, что нужно сделать, это убедиться, что установлена ​​платформа .Net 4.0 - для полной версии она занимает всего 49 МБ, поэтому она невелика.

1 голос
/ 25 мая 2011

Основная проблема здесь в том, что вы не можете запустить код, скомпилированный для .NET 3.5, в .NET 4 CLR или наоборот.Вам нужно снова перекомпилировать для .NET4.

Таким образом, у вас будет 2 исполняемых файла, один для .NET 3.5 и второй для .NET 4. Оба будут иметь одинаковый код, но вы можете использовать Директивы препроцессора , конкретно директива #IF, для различия между этими двумя.

Затем вы указываете конкретную директиву в конфигурации обоих проектов.

0 голосов
/ 25 мая 2011

Нет, потому что вы не можете использовать функции .NET 4 без .NET 4 CLR.Проблема в том, что сборки привязываются во время загрузки, а сборка привязывается к конкретной версии для CLR, для которой вы скомпилировали.

...