如何可重复地引起/引发一个reflectiontypeloadeexception



遗憾的是,引用此异常通常具有奇异的性质,并且可能在您例如通过Assembly.GetTypes()枚举类型时发生-例如,它发生在我们的一个部署中,但同一组程序集在集成服务器上运行良好。

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

因此,任何指针都是有用的,例如,只要知道是什么样的东西导致了这个异常。

<罢工> 编辑我的尝试到目前为止:

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

但我只设法得到一个TypeLoadException与一个非常明确的错误信息

导致此异常的原因如下:

程序集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的方法,但你需要从BC中派生AC:

public class AC : BC
{
}

使用LoaderExceptions属性,您可以检索导致此ReflectionTypeLoadException的异常。在我的例子中,这是一个TypeLoadException,说明它不能加载什么类型

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

使用mock,您将使用IAssemblyService而不是直接在Assembly上调用GetTypes。在模拟中,可以抛出所需的异常。使用像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();
    }
}

和一个mock框架,如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...
}

相关内容

  • 没有找到相关文章

最新更新