Сборки Framework 4.5 загружаются при отладке проекта, ориентированного на Framework 4.0.
Мне нужно иметь возможность ориентироваться на.NET Framework 4.0 с помощью Visual Studio 2012 и проверять, будет ли мой код работать правильно при развертывании в нашей среде 4.0 (Windows Server 2003).
Многоцелевой таргетинг в Visual Studio 2012, кажется, работает правильно, но только для mscorlib.dll
, При обращении к любой другой платформе DLL для компиляции вы получаете правильные ошибки, например, для ссылки на тип, который не существует в 4.0, но версия 4.5 DLL загружается во время выполнения и отладки.
Это делает невозможным проверку правильности работы моего кода в производственной среде с учетом серьезных изменений в обновлении на месте, которые внесла версия 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(".");
}
});
}
Framework 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(".");
}
});
}
Тесты против других библиотек инфраструктуры
Эти тесты, однако, не работают правильно (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));
}
Рамки 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 для всех остальных сборок.
Есть ли способ получить желаемую функциональность?
Обновить
Вот решение / проекты, которые я использую.
2 ответа
Спасибо за отличное воспроизведение!
Когда вы смотрите на ваш проект, на ваши результаты влияют две вещи:
1) Когда мы обнаруживаем приложение 4.0, работающее под 4.5, мы "подкладываем" измененные API-интерфейсы, чтобы вернуть старое поведение 4.0, когда считаем его наблюдаемым при разумном (то есть не надуманном) использовании приложения. Например, приложение 4.0, которое полагалось на возможность изменять список в List.ForEach, продолжит видеть поведение 4.0 независимо от того, работает ли оно под 4.0 или 4.5. 4.5 приложения увидят новое поведение.
Чтобы определить, что мы считаем разумным использованием, и руководствоваться API-интерфейсами, которыми мы руководствуемся, у нас есть команда по совместимости, которая отвечает за рассмотрение каждого "прорывающего" изменения во всей среде и сравнение его с набором правил и рекомендаций, которые мы " за последние 10 лет.
В проекте, который вы прикрепили, есть 5 вещей, которые вы тестируете:
- List.ForEach под 4.5 создает исключение InvalidOperationException при изменении списка
- Uri до 4.5 теперь сохраняет точки в хвостовых сегментах
- Ури под 4.5 больше не убегает? в файле://- на основе URI
- 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
Насколько я понимаю, именно так и должно работать. На вашем компьютере и в вашем GAC нет.NET 4.0. Во время выполнения у вас всегда есть.NET 4.5, потому что это обновление на месте (установка.NET 4.5 перезаписывает.NET 4.0). Сборки со ссылками и многоцелевой таргетинг работают только для IntelliSense, Object Browser и MSBuild (инструменты времени разработки в целом).