Сборки Framework 4.5 загружаются при отладке проекта, ориентированного на платформу 4.0.

Мне нужно настроить таргетинг на .NET Framework 4.0 с помощью Visual Studio 2012 и убедиться, что мой код будет работать правильно при развертывании в нашей среде 4.0 (Windows Server 2003).

Мультитаргетинг в Visual Studio 2012 работает правильно, но только для mscorlib.dll. При ссылке на любую другую библиотеку DLL для компиляции вы получаете правильные ошибки, например. ссылка на тип, который не существует в версии 4.0, но версия DLL версии 4.5 загружается во время выполнения и отладки.

Это делает невозможным проверку того, что мой код будет правильно работать в производственной среде, учитывая критические изменения в обновлении на месте, которое было сделано в версии 4.5 фреймворка.

Я провел несколько модульных тестов, чтобы протестировать функциональность множественного таргетинга, проверив некоторые различия между 4.0 и 4.5, найденные на MSDN. Тесты содержатся в собственных проектах, ориентированных на версию фреймворка, которую они тестируют. Все тесты должны пройти успешно.

Тесты против MSCORLIB

Эти тесты проходят успешно, так как List<string> находится в mscorlib.dll:

Framework 4.0: -проходит-

[TestMethod]
public void List_Foreach_should_not_throw_if_list_is_modified() {
    var list = new List<string> { "This", "here", "be", "a", "list", "of", "strings" };

    list.ForEach((s) => {
        if (s.Equals("be", StringComparison.OrdinalIgnoreCase)) {
            list.Add(".");
        }
    });
}

Структура 4.5: -проходит-

[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void List_Foreach_should_throw_if_list_is_modified() {
    var list = new List<string> { "This", "here", "be", "a", "list", "of", "strings" };

    list.ForEach((s) => {
        if (s.Equals("be", StringComparison.OrdinalIgnoreCase)) {
            list.Add(".");
        }
    });
}

Тесты на другие библиотеки DLL фреймворка

Однако эти тесты не работают правильно (тест 4.5 проходит, тест 4.0 — нет), поскольку эти типы находятся в System.ComponentModel.Composition.dll, а всегда загружается версия 4.5:

Framework 4.0 - сбой, выдает исключение, ожидаемое для 4.5-

[TestMethod]
public void Should_be_able_to_create_a_serializer_for_MEF_catalogs()
{
    var catalog = new AggregateCatalog();
    var serializer = new XmlSerializer(typeof(AggregateCatalog));
}

Framework 4.5 -проходит-

[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void Should_not_be_able_to_create_a_serializer_for_MEF_catalogs()
{
    var catalog = new AggregateCatalog();
    var serializer = new XmlSerializer(typeof(AggregateCatalog));
}

Это так, как задумано? Это кажется непересекающимся, учитывая, что загружена версия mscorlib 4.0, но версия 4.5 любой другой сборки.

Есть ли способ получить желаемую функциональность?

Обновить

Вот решения/проекты, которые я использую.


person joshperry    schedule 25.09.2012    source источник
comment
Все ли ваши ссылки установлены правильно?   -  person Styxxy    schedule 26.09.2012
comment
Мы получили от Дэвида Кина отчет об ошибке в поведении модульного теста. Мы изучим и рассмотрим этот отзыв в будущем обновлении VS. Мэтью Аниян Группа модульного тестирования Visual Studio.   -  person Mathew Aniyan    schedule 23.10.2012


Ответы (2)


Спасибо за отличный репортаж!

Когда вы смотрите на свой проект, есть две вещи, которые влияют на ваши результаты, что приводит к поведению, которое вы видите:

1) Когда мы обнаруживаем приложение версии 4.0, работающее под версией 4.5, мы "подшиваем" измененные API, чтобы вернуть старое поведение версии 4.0, когда мы считаем, что это можно наблюдать при разумном (т.е. не надуманном) использовании приложения. Например, приложение версии 4.0, которое полагалось на возможность изменения списка в List.ForEach, будет по-прежнему вести себя так же, как в версии 4.0, независимо от того, работает ли оно под версией 4.0 или 4.5. Приложения 4.5 увидят новое поведение.

Чтобы определить, что мы считаем разумным использованием, и направлять API, которые мы подгоняем, у нас есть группа совместимости, которая отвечает за просмотр каждого отдельного «критического» изменения во всей структуре и сравнение его с набором правил и руководств, которые мы ve создан за последние 10 лет.

В приложенном вами проекте есть 5 вещей, которые вы тестируете:

  • List.ForEach ниже 4.5 выдает InvalidOperationException при изменении списка.
  • Uri до 4.5 теперь сохраняет хвостовые точки в сегментах пути.
  • Uri под 4.5 больше не убегает? в URI на основе file://
  • Enumerable.Empty в версии 4.5 теперь гарантирует, что он возвращает один и тот же экземпляр (это немного вводит в заблуждение в документации [я зарегистрировал ошибку], я полагаю, что поведение было на 4.0, что он мог вернуть два разных экземпляра в первый раз, когда он к нему одновременно обращались два разных потока на многопроцессорной машине в одно и то же время)
  • Каталоги MEF больше не сериализуются в формате XML.

Из этих поведений первые три изменены, чтобы вернуть предыдущее поведение в 4.5, когда запущено приложение 4.0. Принимая во внимание, что последние два не имеют прокладок. Это связано с тем, что для нарушения последних двух изменений потребуется очень надуманное использование приложений, и в этом случае мы просто документируем их в приведенном выше виде как FYI. Например, возьмем изменение каталога MEF, хотя теоретически вы могли сериализовать эти типы с помощью XML-сериализатора (что было непреднамеренно и, ИМХО, ужасное поведение XML-сериализатора), вы ничего не могли сделать с результатом, поскольку он не дезеркализировать на что-нибудь полезное.

Я пытаюсь выяснить, можем ли мы изменить эту страницу, включив в нее список критических изменений, замаскированных для приложения версии 4.0.

2) Вторая проблема, с которой я столкнулся, заключалась в том, что тестовый проект 4.0 неправильно определялся как 4.5, когда он выполнялся в том же запуске, что и другой тестовый проект на основе 4.5. Вы можете наблюдать это, запустив тесты 4.0 сами по себе, и три шиммерных будут пройдены. Запустите их вместе с тестами 4.5, и они потерпят неудачу. Я не уверен, где эта проблема вступает в игру, но я зарегистрировал ошибку внутри компании и запустил ветку с ответственной командой, чтобы разобраться в ней. Если вы хотите отслеживать проблему извне, не стесняйтесь сообщить об ошибке на http://connect.microsoft.com/VisualStudio, и мы направим его правильным владельцам.

Дэвид Кин

Команда CLR

person David Kean    schedule 26.09.2012
comment
У меня есть один вопрос, на который я до сих пор нигде не получил ответа: ПОЧЕМУ? Зачем вся эта сложность и плохо документированное волшебство вместо того, чтобы просто увеличивать версию и делать все, как положено в мире .NET? Даже с хорошей документацией это никогда не станет ясно. Обновление на месте — одно из худших архитектурных решений, которое вы можете сделать в мире .NET, так почему же оно применяется к самой .NET? - person Ladislav Mrnka; 26.09.2012
comment
Ух ты! Спасибо, Дэвид, за невероятно подробный ответ. Зная о шиммированном поведении, теперь все становится намного понятнее. Я очень ценю, что вы нашли время, чтобы посмотреть на это и ответить. Что касается вашего № 2, я заметил такое же поведение и, с моим неправильным взглядом на проблему, предположил, что это симптом того же; то есть, возможно, все тесты выполнялись под общим доменом приложения, в котором были загружены сборки 4.5. В итоге я сделал то же, что и вы, выполнив два набора тестов вручную и независимо. - person joshperry; 26.09.2012

Насколько я понимаю, именно так оно и должно работать. На вашем компьютере и в вашем GAC нет .NET 4.0. Во время выполнения у вас всегда будет .NET 4.5, потому что это обновление на месте (установка .NET 4.5 перезаписывает .NET 4.0). Ссылочные сборки и множественное нацеливание работают только для IntelliSense, Object Browser и MSBuild (инструменты времени разработки в целом).

person Ladislav Mrnka    schedule 25.09.2012
comment
Если бы это было правдой, то как и почему Visual Studio загружает версию 4.0 mscorlib.dll при отладке проекта, ориентированного на платформу 4.0, и версию 4.5 mscorlib.dll при отладке проекта, ориентированного на 4.5? - person joshperry; 26.09.2012
comment
Я попрошу разработчика подробно ответить на этот вопрос сегодня вечером. - person Scott Hanselman; 26.09.2012