【问题标题】:RTTI on objects in DelphiDelphi中对象的RTTI
【发布时间】:2010-09-15 04:04:02
【问题描述】:

我正在尝试在 Delphi 中将对象解析为 XML,因此我阅读了有关调用对象的 ClassInfo 方法以获取其 RTTI 信息的信息。

问题是,这显然只适用于 TPersistent 对象。否则,我必须在源代码中专门添加一个编译器指令 {$M+},以便编译器生成 RTTI 信息。

所以我很高兴地添加了指令,结果发现,即使它确实从 ClassInfo 调用中返回了某些内容(它曾经返回 nil),现在我也无法从中检索类的属性、字段或方法。就像它创建的对象是空的。

知道我在这里缺少什么吗?谢谢!

【问题讨论】:

    标签: delphi rtti


    【解决方案1】:

    至于只返回 nil 的 RttiType 问题,这可能有一个原因:在您的测试中,您没有在任何时候实例化该类。编译器因为它从来没有对这个类的引用(因为它根本不是一个实例),所以作为一种优化形式,它只是从信息中删除它。请参阅下面的两个示例。当您在代码中的某个位置实例化类时,行为会有所不同。

    假设以下类:

    type
      TTest = class
      public
        procedure Test;
      end;
    

    以及下面的代码:

    var
      LContext: TRttiContext;
      LType: TRttiType;
      LTest: TTest;
    begin
      LContext := TRttiContext.Create;
      for LType in LContext.GetTypes do
      begin
        if LType.IsInstance then
        begin
          WriteLn(LType.Name);
        end;
      end;
    end;
    

    到目前为止,RTTI 无法使用 TTest 类信息。但是,当我们在应用程序中创建某个点时,会在编译中为它创建一个引用,从而使这些信息可用:

    var
      LContext: TRttiContext;
      LType: TRttiType;
      LTest: TTest;
    begin
      LTest := TTest.Create; //Here i´m using TTest.
                             //Could be in another part of the program
    
      LContext := TRttiContext.Create;
      for LType in LContext.GetTypes do
      begin
        if LType.IsInstance then
        begin
          WriteLn(LType.Name);
        end;
      end;
    end;
    

    此时,如果您使用LContext.FindType ('TTest'),则不会返回nil,因为编译器保留了对该类的引用。这解释了您在测试中的行为。

    【讨论】:

      【解决方案2】:

      您是否将这些属性和方法放入published 部分?

      除此之外,“经典”RTTI ($TYPEINFO ON) 只会为您提供有关属性的信息,而不是有关方法的信息。你需要'扩展'RTTI ($METHODINFO ON)。

      扩展 RTTI 的良好起点:David Glassborow on extended RTTI

      (谁会相信,就在这一分钟,我写完了一些使用扩展 RTTI 的代码,并决定浏览一下 Stack Overflow:))

      【讨论】:

      • 谢谢,这一定是问题所在。我将这些财产公开,而不是公开的部分。我得等到星期一再试,因为我在工作中做 Delphy,而且我已经回家过周末了。
      【解决方案3】:

      您是否考虑过使用 TXMLDocument 组件?它将查看您的 XML,然后创建一个很好的 Delphi 类单元来表示您的 XML 文件——使读写 XML 文件变得非常非常容易。

      【讨论】:

      • TXMLDocument 会这样吗?我以为是 XML 数据绑定向导做到了... ;)
      【解决方案4】:

      RTTI 只会向您显示 已发布 属性等。 - 不只是公开的。

      用 TObject 试试你的代码,看看会发生什么 - 如果这不起作用,发布你的代码,因为不是每个人都通灵。

      【讨论】:

      • 这就是问题所在,我的属性只是公开的,没有发布。周一回来上班的时候试试。谢谢!
      • delphi 中的经典 RTTI 显示 PUBLISHED 属性,“新扩展 RTTI”实际上可以看到所有内容,但需要最近的 Delphi 版本(2010/XE 或更高版本)。
      猜你喜欢
      • 1970-01-01
      • 2011-03-05
      • 1970-01-01
      • 2012-09-22
      • 2011-04-27
      • 1970-01-01
      • 2011-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多