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
(например, метод получения свойства), тогда вы должны использовать тип возврата метода, который вы вызвали (также извлеченный из сигнатуры метода.) - Если вы получили значение из поля, извлеките тип из сигнатуры поля.
- Если вы разыгрываете значение, тогда используйте тот тип, который вы используете.