我们正在使用.NET 4.5,直到一个月前突然停止工作时,MEF中的开放式通用导出也没有问题。我们的CI服务器上的70个测试变为红色,我们将其追溯到容器中缺少的部分。
我发现它很奇怪,所以我写了这个测试代码:
var catalog = new TypeCatalog(typeof(Impersonator<>), typeof(Cache<>));
var parts = catalog.Parts;
但看起来没有任何开放的泛型类型会在目录中注册。 Parts
是TypeCatalog
Types = <Empty>
。
通常我们通过使用this SO question中的属性的声明性导出来解决这个问题,但是没有一个替代方案似乎已经起作用了。
任何想法都会受到最高的赞赏。
答案 0 :(得分:2)
知道什么触发它开始失败了吗?您是否在该时间范围内获得了.NET更新?
出于好奇,如果你写一个针对.NET 4.5的简单控制台应用程序,这个问题是否重现?
我问的原因是我相信有一个针对.NET 4.5发布的更新,以确保打开的泛型不破坏现有的.NET 4.0应用程序,因此如果出于某种原因,您的测试在.NET 4.0模式下运行,那么将禁用开放式通用支持,这可能会导致您所看到的内容。
答案 1 :(得分:2)
我在我的网络应用中通过输入条目&lt; httpRuntime targetFramework =“4.5”/&gt;在我的web.config中。对于非Web应用程序,请确保app.config具有该条目 &LT; supportedRuntime version =“v4.0”sku =“。NETFramework,Version = v4.5”/&gt;。
请参阅http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime-targetframework.aspx了解详情。
答案 2 :(得分:1)
我知道这是一个老问题,但我有一些可能对其他人有帮助的其他信息。
我遇到了同样的问题。我的单元测试工作然后突然停止。我们将其缩小为一对Windows更新:KB2840642v2和KB2840642。卸载这些后,MEF在单元测试中再次开始正常工作。我没有在发行说明中看到任何可能影响事情的更新,但你知道这是怎么回事。
然而,不幸的是,我现在正在运行Windows 8,并且问题又出现了。我没有安装这些更新。我认为它们本身已合并到操作系统中。
答案 3 :(得分:1)
当您说“在我们的CI服务器上”时,这并没有告诉我们您如何运行测试。但是,我似乎使用vstest.console.exe
获得了与您相同的体验。
我发现MEF的自动开放式关闭功能(.net-4.5中的新功能)在使用vstest.console.exe
运行测试时似乎会中断。基本上,vstest.console.exe
可能决定在.net-4.0兼容模式下运行,就像传递了/Framework:Framework40
一样。即使由.net-4.0运行时加载,.net-4.5程序集也会加载并运行完全正常,但MEF检测到您正在.net-4.0模式下运行并禁用其对自动关闭开放泛型类型的支持。您可以通过传递vstest.console.exe
开关强制/Framework:Framework45
以.net-4.5模式运行来让MEF再次正常运行。
(这在安装了.net-4.6.1的计算机上进行了测试,但不确定这是否会改变更多内容)。
当我针对.net-4.5框架创建一个简单的测试程序集时,vstest.console.exe
正确地猜测它应该使用.net-4.5运行测试。但是,当我组装一个集成到更复杂的构建环境的程序集时,vstest.console.exe
突然开始以.net-4.0模式而不是.net-4.5模式运行。所以我从复杂的构建环境开始,开始削减一切,直到问题消失。
要让vstest.console.exe
猜错框架,需要两个程序集。在一个方面,定义自定义程序集Attribute
。在另一个应用程序中,应用该自定义程序集属性并定义单元测试。
第一次集会:
using System;
[AttributeUsage(AttributeTargets.Assembly)]
public class BreakVSTestFrameworkDetectionAttribute : Attribute
{
}
引用前一个程序集的第二个程序集:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
[assembly: BreakVSTestFrameworkDetection]
[InheritedExport]
public interface IGenericService<T>
{
void Print(T thing);
}
public class SomeGenericService<T> : IGenericService<T>
{
public void Print(T thing) => Console.WriteLine($"{typeof(T)}:{thing}");
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Run()
{
using (var catalogue = new ApplicationCatalog())
using (var container = new CompositionContainer(catalogue))
{
container.GetExportedValue<IGenericService<string>>().Print("asdf"); // System.String:asdf
container.GetExportedValue<IGenericService<int>>().Print(123); // System.Int32:123
}
}
static void Main(string[] args) => new UnitTest1().Run();
}
通过这两个程序集和定义的测试,我在不同的场景中得到以下结果:
使用Visual Studio 2015社区版的GUI运行测试非常合适。
直接将代码作为可执行文件运行正常。
C:\Users\ohnob\OneDrive\Documents\Visual Studio 2015\Projects\MefGenericsUnitTests>bin\Debug\MefGenericsUnitTests.exe
System.String:asdf
System.Int32:123
使用像mstest(except I can’t tell why one would or wouldn’t use this instead of vstest)之类的东西运行测试会神奇地起作用(至少在这种情况下)(输出修剪)。
C:\Users\ohnob\OneDrive\Documents\Visual Studio 2015\Projects\MefGenericsUnitTests>"\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\MSTest.exe" /testcontainer:bin\Debug\MefGenericsUnitTests.exe
Microsoft (R) Test Execution Command Line Tool Version 14.0.23107.0
Copyright (c) Microsoft Corporation. All rights reserved.
Loading bin\Debug\MefGenericsUnitTests.exe...
Starting execution...
Results Top Level Tests
------- ---------------
Passed UnitTest1.Run
1/1 test(s) Passed
直线上升vstest.console.exe
失败(输出修剪):
C:\Users\ohnob\OneDrive\Documents\Visual Studio 2015\Projects\MefGenericsUnitTests>"\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" bin\Debug\MefGenericsUnitTests.exe
Microsoft (R) Test Execution Command Line Tool Version 14.0.24720.0
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
Failed Run
Error Message:
Test method UnitTest1.Run threw exception:
System.ComponentModel.Composition.ImportCardinalityMismatchException: No exports were found that match the constraint:
ContractName IGenericService(System.String)
RequiredTypeIdentity IGenericService(System.String)
但是vstest.console.exe /Framework:Framework45
成功了:
C:\Users\ohnob\OneDrive\Documents\Visual Studio 2015\Projects\MefGenericsUnitTests>"\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" /Framework:Framework45 bin\Debug\MefGenericsUnitTests.exe
Microsoft (R) Test Execution Command Line Tool Version 14.0.24720.0
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
Passed Run
Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 3.7855 Seconds
答案 4 :(得分:0)
我认为你不能使用open generic,应该提供一个具体的运行类,如:
var catalog = new TypeCatalog(typeof(Impersonator<type1>), typeof(Impersonator<type2>), typeof(Cache<type3>), typeof(Cache<type4>));
var parts = catalog.Parts;
我尝试使用IImpersonator和ICache等接口,但也不起作用:
interface IImpersonator { }
class Impersonator<T> : IImpersonator
...
var catalog = new TypeCatalog(typeof(IImpersonator), typeof(ICache));
var parts = catalog.Parts;