2

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

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

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

知道我在这里想念什么吗?谢谢!

4

4 回答 4

7

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

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

扩展 RTTI 的良好起点:David Glassborow 谈扩展 RTTI

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

于 2008-10-03T19:25:03.453 回答
3

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

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

于 2008-10-03T19:22:43.660 回答
3

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

于 2008-10-04T05:27:48.540 回答
0

至于只返回 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,因为编译器保留了对该类的引用。这解释了您在测试中的行为。

于 2017-09-16T12:12:51.190 回答