我正在尝试在Delphi中将对象解析为XML,所以我读到了调用对象的ClassInfo方法来获取其RTTI信息。
问题是,这显然只适用于TPersistent对象。否则,我必须在编译器的源代码中专门添加一个编译器指令{$ M +}来生成RTTI信息。
所以我很高兴地添加了该指令,只是为了发现它,即使它确实从ClassInfo调用中返回了一些东西(它曾经返回nil),现在我无法从中检索类的属性,字段或方法。这就像是把对象创建为空。
知道我在这里缺少什么吗?谢谢!
答案 0 :(得分:7)
您是否已将这些属性和方法放入published
部分?
除此之外,'经典'RTTI($ TYPEINFO ON)只会获取有关属性的信息,而不是方法。你需要'扩展'RTTI($ METHODINFO ON)。
扩展RTTI的良好起点:David Glassborow on extended RTTI
(谁会相信这一刻我写完了一些使用扩展RTTI的代码并决定稍微浏览Stack Overflow :))
答案 1 :(得分:3)
RTTI只会向您显示已发布的属性等。 - 不只是公开的。
使用TObject尝试你的代码,看看会发生什么 - 如果这不起作用,发布你的代码,因为不是每个人都是通灵的。
答案 2 :(得分:3)
您是否考虑过使用TXMLDocument组件?它将查看您的XML,然后创建一个代表您的XML文件的Delphi类的良好单元 - 使其真正,非常容易地读取和写入XML文件。
答案 3 :(得分: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,因为编译器会继续引用该类。这解释了您在测试中的行为。