3

我正在尝试重新创建一个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; }
}

虽然版本 2TheLibrary的接口看起来像:

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

public interface IShrinkingThing
{ }

ProxyForV2有这个实现版本 2.0 的类IShrinkingThing

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

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

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

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

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

测试方法 TestProject.LoadTester.ShrinkingThingBreaks 抛出异常:System.TypeLoadException:方法 'get_RemovedProperty' in type 'ProxyForV2.ShrinkingThingImpl' from assembly 'ProxyForV2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 没有实现。 .

所以 aTypeLoadException被抛出,虽然它唯一可能被抛出的地方是在一个try带有 a 的块中catch (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()导致这种 un-catchable TypeLoadException,因此很明显,当 .NET 尝试加载类时,而不是来自任何分配时,问题就产生了。

我减轻这个问题的唯一想法是尝试在不同的应用程序域中加载类型,这样它就不会干扰,然后做一些疯狂的反射来查看接口是否与实现兼容,但这似乎是完整的和完全的矫枉过正。

总结:为什么似乎不可能以“正常”的方式捕捉到这个问题,我该如何在运行时解决这样的问题?

4

1 回答 1

6

类型在使用它们的方法开始执行之前被加载。为此,您需要:

[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();
}
于 2010-07-27T19:05:35.777 回答