【问题标题】:Func-eval on polymorphic classes多态类的函数评估
【发布时间】:2016-08-08 07:52:21
【问题描述】:

我正在使用 MDBG 示例制作托管 .NET 调试器。

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 类而不是 Base 类。 那时我无法再区分调用哪个方法 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
        );

【问题讨论】:

  • 将对象转换为它的基类不会改变对象,只会改变它的感知方式。我建议您需要将“感知”类型与值一起传递,并使用它而不是实际类型来找到正确的方法。
  • @BrianReichle 感谢您的建议!但是我没有“感知”类型,调试器应该如何知道对对象执行了什么转换?
  • 也许“静态确定类型”比“感知”类型更好。您可以从获得值的任何地方获取它(字段类型、参数类型、方法/属性返回类型等......)
  • @BrianReichle 你的意思是编译器时间类型吗?所以为了得到它,我应该以某种方式调用 roslyn,给它我的运行时已知的类名、方法名和变量名来获取静态类型?
  • 不,当我说“静态确定类型”时,我指的是通过查看代码/元数据而不是通过运行它或检查当前执行状态获得的类型。所以如果从参数中获取值,静态确定的类型就是参数的类型。如果你从一个属性中得到它,那么它就是属性的类型。

标签: c# clr cil mdbg imetadataimport


【解决方案1】:

将对象转换为它的基类不会改变对象的类型,只会改变它的感知方式。我建议您需要将“感知”类型与值一起传递,并使用它而不是实际类型来找到正确的方法。

“感知”类型是根据您从何处获取值而静态确定的类型。

  • 如果您使用ICorDebugILFrame::GetArgument() 从参数中获取值,则从方法签名中提取相应的参数类型。
    • 如果它的第一个参数和方法签名具有HasThis 标志但没有ExplicitThis 标志,则改为从值中获取类型。
  • 如果您使用 ICorDebugILFrame::GetLocalVariable() 从本地获取值,则从方法本地签名中提取类型(本地签名的元数据标记需要从方法头中提取。)
  • 如果您通过运行带有ICorDebugEval 的方法(例如属性getter)获得了值,那么您应该使用您调用的方法的返回类型(也从方法签名中提取)。
  • 如果您从字段中获取值,则从字段签名中提取类型。
  • 如果您转换了一个值,则使用您要转换的任何类型。

【讨论】:

  • 谢谢你,布赖恩!你的回答使我免于淹没在这片疑惑的海洋中。我想现在我开始明白你的意思了,但我需要一些时间来尝试一下,看看我会得到什么。在概念层面上唯一不清楚的是最后一段关于演员表的内容。在那种情况下,我没有要解析的方法签名/字段签名,那么从哪里可以得到我要转换的类型?
  • 这只是假设在某些时候您可能希望在调试器中评估表达式时支持强制转换。例如。 ((A)castedToBase).SomeProp ...也许现在担心这个还为时过早:)
  • 是的,你是对的,当我输入你提到的一些表达方式时,现在想当然还为时过早!我在想的是一些代码,而不是调试器表达式。就像在问题的示例中一样:var castedToBase = (Base)a;,然后我想简单地评估在调试器中执行castedToBase.SomeProp 的属性。目前我坚持评估字段和属性,没有更高级的......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 2017-06-10
  • 2015-12-01
相关资源
最近更新 更多