我正在尝试重新创建TypeLoadException以便进行演示,因此我有一个看起来像这样的荒谬愚蠢的库设置:

TestProject --> TheLibrary [1.0]
            \-> ProxyForV2 -> TheLibrary [2.0]


TheLibrary版本1具有以下相关接口:

public interface IConsistentThing
{
    int ConsistentProperty { get; set; }
}

public interface IShrinkingThing
{
    int RemovedProperty { get; set; }
}


TheLibrary的界面的版本2如下所示:

public interface IConsistentThing
{
    int ConsistentProperty { get; set; }
}

public interface IShrinkingThing
{ }


ProxyForV2具有实现2.0 IShrinkingThing版本的此类:

public class ShrinkingThingImpl : IShrinkingThing
{
    public int ConsistentProperty { get; set; }
}


因此,在TestProject中,如果有人尝试分配TypeLoadException,我期望引起ProxyForV2.ShrinkingThingImpl,因为接口的第一个版本具有第二个版本未实现的属性。为了证明这一点,我有一个单元测试,如下所示:

[TestMethod]
public void ShrinkingThingBreaks()
{
    try
    {
        IShrinkingThing thing = new ProxyForV2.ShrinkingThingImpl();

        Assert.Fail("This should have caused a TypeLoadException");
    }
    catch (TypeLoadException)
    {
        //  valid
    }
}


这是我的问题:此单元测试失败。但不是由于我的Assert.Fail,正如我期望的那样。测试输出如下所示:


  测试方法TestProject.LoadTester.ShrinkingThingBreaks引发了异常:System.TypeLoadException:程序集“ ProxyForV2”中版本为“ ProxyForV2.ShrinkingThingImpl”的方法“ get_RemovedProperty”,版本为1.0.0.0,Culture = neutral,PublicKeyToken = null没有实现。 。


因此,将抛出一个TypeLoadException,尽管它唯一可能被抛出的位置是带有trycatch (TypeLoadException)块中,但是该异常拒绝被捕获。除此之外,即使我使用了包罗万象的内容,单元测试也会失败,并返回与以前相同的错误:

[TestMethod]
public void ShrinkingThingBreaks()
{
    try
    {
        IShrinkingThing thing = new ProxyForV2.ShrinkingThingImpl();

        Assert.Fail("This should have caused a TypeLoadException");
    }
    catch
    {
        //  valid
    }
}


到底是怎么回事?显然,这是一个完全人为设计的方案,但是我仍然想知道发生了什么,以便可以在运行时避免此错误,或者至少在发生这种错误时予以解决(是的,我知道最终的解决方案是确保所有库版本均相同)。

最糟糕的部分是,对类的所有访问(例如typeof(ProxyForV2.ConsistentThingImpl)ProxyForV2.ConsistentThingImpl.SomeStaticFunction())都会导致此无法捕获的TypeLoadException,因此,很明显,问题出在.NET尝试完全加载类时,不是来自任何任务。

缓解此问题的唯一想法是尝试将类型加载到其他应用程序域中,以免干扰,然后进行一些疯狂的思考,以查看接口是否与实现兼容,但这似乎是完整的和完整的过度杀伤力。

总结:为什么似乎无法以“正常”方式捕获此问题,并且如何在运行时解决此类问题?

最佳答案

在开始使用类型的方法之前,先加载类型。为此,您需要:

[TestMethod]
public void ShrinkingThingBreaks()
{
    try
    {
        InnerShrinkingThingBreaks();

        Assert.Fail("This should have caused a TypeLoadException");
    }
    catch
    {
        //  valid
    }
}

[MethodImpl(MethodImplAttributes.NoInlining)]
private void InnerShrinkingThingBreaks()
{
        IShrinkingThing thing = new ProxyForV2.ShrinkingThingImpl();
}

10-04 12:24