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

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

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

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

有帮助吗?

解决方案

您是否已将这些属性和方法放入已发布的部分?

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

扩展RTTI的良好起点: David Glassborow关于扩展的RTTI

(谁会相信这一刻我写完了一些使用扩展RTTI的代码并决定稍微浏览Stack Overflow :))

其他提示

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

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

您是否考虑过使用TXMLDocument组件?它将查看您的XML,然后创建一个代表您的XML文件的Delphi类的好单元 - 使其真正,非常容易地读取和写入XML文件。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top