Func-eval на полиморфных классах

Я делаю управляемый.NET отладчик, используя пример MDBG.

Образец MDBG работает только с классом верхнего уровня данного экземпляра, не ища глубоко внутри иерархии классов. Мне удалось пройти иерархию и получить все доступные методы. Но проблема возникает в таком случае:

    public abstract class Base{
        public Base() {SomeProp = "Base"}
        public string SomeProp {get;set;}
    }

    public class A : Base{
        public Base() {SomeProp = "A"}
        public new string SomeProp {get;set;}
    }

    public static void Main(){
        var a = new A();
        var castedToBase = (Base)a;
        //castedToBase.SomeProp -- expect result to be "Base" when debugging
    }

Проблема в том, что когда я получаю castedToBase как ICorDebugValue и запрашиваю его ICorDebugValue2::GetExactType, я получаю класс A вместо базового класса. В этот момент я больше не могу различить, какой метод get_SomeProp вызывать. Я ожидал бы, что ICorDebugValue2::GetExactType будет принимать во внимание выполненные приведения и не всегда будет возвращать базовый тип.

Как я могу понять, какой метод я должен вызвать?

Некоторый код того, что я делаю сейчас, указан ниже. mdbgValue представляет объект castedToBase. szTypedef возвращает "A" вместо ожидаемой "Base"

    IMetadataImport importer;
    var classToken = mdbgValue.CorValue.ExactType.Class.Token;

    int size;
    int ptkExtends;
    TypeAttributes pdwTypeDefFlags;
    importer.GetTypeDefProps(classToken,
        null,
        0,
        out size,
        out pdwTypeDefFlags,
        out ptkExtends
        );
    StringBuilder szTypedef = new StringBuilder(size);
    importer.GetTypeDefProps(classToken,
        szTypedef,
        szTypedef.Capacity,
        out size,
        out pdwTypeDefFlags,
        out ptkExtends
        );

1 ответ

Решение

Приведение объекта к его базовому классу не меняет тип объекта, только то, как он воспринимается. Я хотел бы предложить вам передать "воспринимаемый" тип вместе со значением и использовать его вместо фактического типа для нахождения правильного метода.

"Воспринимаемый" тип - это статически определенный тип, основанный на том, откуда вы получили значение.

  • Если вы получили значение из параметра, используя ICorDebugILFrame::GetArgument()затем извлеките соответствующий тип аргумента из сигнатуры метода.
    • Если его первый аргумент и сигнатура метода имеет HasThis флаг, но не ExplicitThis вместо этого флаг получает тип из значения.
  • Если вы получили значение от местного использования ICorDebugILFrame::GetLocalVariable() затем извлеките тип из подписи локальных методов (токен метаданных подписи локальных пользователей должен быть извлечен из заголовка метода).
  • Если вы получили значение от запуска метода с ICorDebugEval (например, метод получения свойства), тогда вы должны использовать тип возврата метода, который вы вызвали (также извлеченный из сигнатуры метода.)
  • Если вы получили значение из поля, извлеките тип из сигнатуры поля.
  • Если вы разыгрываете значение, тогда используйте тот тип, который вы используете.
Другие вопросы по тегам