如何重现导致/激发ReflectionTypeLoadException?

时间:2011-08-23 14:05:51

标签: .net exception reflection types

可悲的是,对此异常的引用通常具有异国情调,并且可能在您例如通过Assembly.GetTypes()枚举类型 - 例如,它发生在我们的某个部署上,但同一组程序集在Integration Server上正常工作。

为了加强这种类型的错误,我希望能够引发这样的异常,看看我的异常处理代码是否按预期工作。

因此任何指针都是有用的,例如只知道什么样的事情导致了这个例外。

<击> 修改 到目前为止我的尝试:

  • 在程序集A中定义使用程序集B
  • 属性的类型
  • 让一些代码遍历程序集中的所有类型 属性已指定。
  • 仅在DEBUG标志为真时才构建属性
  • 然后我将该依赖项的发布版本复制到相关文件夹

但我只设法得到一个TypeLoadException,其中包含非常明确的错误消息

2 个答案:

答案 0 :(得分:3)

以下原因导致此异常:

您有程序集A,它定义了以下类:

public class AC
{
    public BC GetBC() { /* ... */ }
}

您有程序集B,它定义了类BC。 现在,当您加载程序集A并获取类AC的成员时,例如使用assembly.GetTypes().SelectMany(t => t.GetMembers()).ToList();,框架会尝试解析BC。它甚至知道它在汇编B中。但是,如果框架解析了不包含B的程序集BC,则会抛出TypeLoadException。如果程序集B不是最新的,可能会发生这种情况,因为您在部署中忘记了它。

<强>更新
要实际获得ReflectionTypeLoadException,场景非常相似。但是,您不需要AC中的方法返回BC,但您需要从AC派生BC

public class AC : BC
{
}

使用LoaderExceptions属性,您可以检索导致此ReflectionTypeLoadException的异常。就我而言,这是一个TypeLoadException,说明它无法加载的类型。

答案 1 :(得分:2)

如果您希望测试代码处理异常的方法,另一种方法是在测试中使用模拟。通过模拟,您可以模拟装配加载子系统,并专注于测试如何处理产生的异常 - 更直接。

使用模拟,您可以使用IAssemblyService而不是直接在GetTypes上调用Assembly。在你的模拟中,你可以抛出所需的异常。使用模拟框架(如FakeItEasy)更常见,但以下使用手动模拟进行演示。

在您的测试中,您将使用MockAssemblyService替换您的实际装配服务。

internal class MyTypeThatLoadsStuff
{
    public MyTypeThatLoadsStuff(IAssemblyService assemblyService)
    {
        //Do stuff with assemblyService
    }
}

internal interface IAssemblyService
{
    IEnumerable<Type> GetTypes();
}

internal class AssemblyService : IAssemblyService
{
    private readonly Assembly _assembly;

    public AssemblyService(Assembly assembly)
    {
        _assembly = assembly;
    }

    public IEnumerable<Type> GetTypes()
    {
        return _assembly.GetTypes();
    }
}

internal class MockAssemblyService : IAssemblyService
{
    public IEnumerable<Type> GetTypes()
    {
        throw new ReflectionTypeLoadException();
    }
}

使用像FakeItEasy这样的模拟框架:

[Test]
public void Test()
{
    IAssemblyService service = A.Fake<IAssemblyService>();

    ReflectionTypeLoadException ex = new ReflectionTypeLoadException(
        new[] { typeof(SprocketTests) }, new[] { new Exception() });

    A.CallTo(() => service.GetTypes()).Throws(ex);

    MyTypeThatLoadsStuff loader = new MyTypeThatLoadsStuff(service);

    //test...
}