Исключением TypeLoadException не является try / catch - PullRequest
3 голосов
/ 27 июля 2010

Я пытаюсь воссоздать 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: метод 'get_RemovedProperty' в типе 'ProxyForV2.ShrinkingThingImpl' из сборки 'ProxyForV2, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = null 'не имеет реализации ..

Таким образом, TypeLoadException выбрасывается и хотя единственное место, где он может возможно быть брошеннымнаходится в try блоке с 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(), вызывает эту неуловимуюTypeLoadException, поэтому ясно, что проблема возникает, когда .NET пытается загрузить класс вообще, а не из какого-либо назначения.

Моя единственная идея для смягчения этой проблемы - попытаться загрузить тип вдругой домен приложения, чтобы он не вмешивался, а затем делал какие-то безумные размышления, чтобы увидеть, совместим ли интерфейс с реализацией, но это выглядит как полное и полное излишество.

В заключение: почему это кажется невозможнымпоймать эту проблему "нормальным" способом и как я могу решить такие проблемы во время выполнения?

1 Ответ

6 голосов
/ 27 июля 2010

Типы загружаются перед началом выполнения в методе, который их использует. Для этого вам необходимо:

[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();
}
...