3

我需要能够使用 Visual Studio 2012 以 .NET Framework 4.0 为目标,并验证我的代码在部署到我们的 4.0 环境 (Windows Server 2003) 时是否能够正常工作。

Visual Studio 2012 中的多目标功能似乎可以正常工作,但仅适用于mscorlib.dll. 当引用任何其他框架 DLL 时,编译时会出现正确的错误,例如引用 4.0 中不存在的类型,但 DLL 的 4.5 版本在执行和调试期间加载。

考虑到 4.5 版本框架所做的就地升级中的重大更改,这使得无法验证我的代码是否可以在生产环境中正常工作。

我做了一些单元测试,通过执行MSDN上的 4.0 和 4.5 之间的一些差异来测试多目标功能。这些测试包含在他们自己的项目中,这些项目针对他们正在测试的框架版本。所有测试都应该通过。

针对 MSCORLIB 的测试

这些测试成功通过,List<string>位于mscorlib.dll

框架 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 版本:

框架 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 版本似乎是不相交的。

有没有办法获得我想要的功能?

更新

这是我正在使用的解决方案/项目。

4

2 回答 2

2

据我了解,这正是它应该如何工作的。您的计算机和 GAC 中没有 .NET 4.0。在运行时,您始终拥有 .NET 4.5,因为它是就地升级(安装 .NET 4.5 会覆盖 .NET 4.0)。引用的程序集和多目标仅适用于 IntelliSense、对象浏览器和 MSBuild(通常是设计时工具)。

于 2012-09-25T22:17:06.167 回答
2

感谢您的精彩再现!

在查看您的项目时,有两件事会影响您的结果,从而导致您看到的行为:

1)当我们检测到在 4.5 下运行的 4.0 应用程序时,我们“填充”更改 API 以返回旧的 4.0 行为,当我们认为它可以从合理(即非人为的)应用程序使用中观察到时。例如,依赖于在 List.ForEach 中修改列表的能力的 4.0 应用程序将继续看到 4.0 行为,无论是在 4.0 还是 4.5 下运行。4.5 应用程序将看到新的行为。

为了确定我们认为合理的使用方式,并指导我们填充的 API,我们有一个兼容性团队负责检查整个框架中的每一个“重大”更改,并将其与我们的一组规则和指南进行比较。在过去的 10 年里建立起来。

在您附加的项目中,您正在测试 5 件事:

  • 4.5下的List.ForEach修改列表时抛出InvalidOperationException
  • Uri 低于 4.5 现在在路径分段中保留尾点
  • 4.5以下的Uri不再逃逸?在基于 file:// 的 URI 中
  • 4.5 下的 Enumerable.Empty 现在保证它返回相同的实例(这个在文档中有点误导[我已经提交了一个错误],我相信行为是在 4.0 上,它可以在第一次返回两个不同的实例被多进程机器上的两个不同线程同时访问
  • MEF 的目录不再是 XML 可序列化的

在这些行为中,前三个被填充以在 4.0 应用程序运行时返回 4.5 上的先前行为。然而,最后两个没有填充。这是因为最后两个更改会破坏非常人为的应用程序用法,在这种情况下,我们只是将它们记录在上面作为仅供参考。例如,更改 MEF 目录,虽然理论上您可以使用 XML 序列化程序序列化这些类型(这是无意的,恕我直言,这是 XML 序列化程序的可怕行为),但您无法对结果做任何事情,因为它没有对任何有用的东西进行反序列化。

如果我们可以修改该页面以包含为 4.0 应用程序填充的重大更改列表,我正在追赶。

2)我遇到的第二个问题是 4.0 测试项目与另一个基于 4.5 的测试项目在同一运行时被错误地检测为 4.5。您可以通过自己运行 4.0 测试来观察这一点,三个带垫片的测试将通过。将它们与 4.5 测试一起运行,它们会失败。我不确定这个问题在哪里发挥作用,但我已经在内部提交了一个错误,并与负责的团队启动了一个线程以深入了解它。如果您想在外部跟踪问题,请随时在http://connect.microsoft.com/VisualStudio上提交错误,我们会将其发送给正确的所有者。

大卫·基恩

CLR 团队

于 2012-09-26T02:10:15.463 回答