如何在Delphi中纯粹通过RTTI信息(即不使用任何实际对象实例)获取
我正在使用RTTI实现用于流式传输任意Delphi对象的通用代码,并且为了使其工作(更具体地说,为了使加载部分工作),我需要以某种方式获得TObjectList的子项类型< ; T>不使用任何实际对象实例的字段.
要求不使用任何实际对象实例的明显原因是,在从流加载对象的情况下(仅基于要加载的对象的类类型的知识),我将不会有任何实例在加载完成之前完全可用 – 我宁愿只能访问相关类的纯RTTI数据. 我希望能够加载的这样一个类的示例如下: TTestClass = class(TObject) public test_list : TList<string>; end; 我想要的是能够得出结论test_list字段是通用TList< T>.其中T是字符串(即,为了知道从子流的流中期望什么数据). 如果该课程反而如下: TTestClassWithArr = class(TObject) public test_arr : array of string; end; 我可以使用test_arr字段的TRttiDynamicArrayType RTTI类的ElementType()方法纯粹通过RTTI提取此信息,但是我找不到TObjectList< T>的任何相应的这种显式RTTI类型. 另一个Stack Overflow问题(Delphi Rtti: how to get objects from 通过单独使用类的RTTI信息,确实应该有某种方法来实现这一点,因为无论对象实例化如何,所有类型信息显然都是在编译时为它提供的. 解决方法
不幸的是,没有为通用参数生成RTTI.在像TList< T>这样的通用容器中发现T值的唯一方法.是获取目标字段本身的TRttiType,调用其ToString()方法将其类名称作为字符串,并解析括号之间的子字符串.例如:
uses ...,System.StrUtils,System.Rtti; var Ctx: TRttiContext; s: string; OpenBracket,CloseBracket: Integer; ... begin ... s := Ctx.GetType(TTestClass).GetField('test_list').FieldType.ToString; // returns 'TList<System.string>' OpenBracket := Pos('<',s); CloseBracket := PosEx('>',s,OpenBracket+1); s := Copy(s,OpenBracket+1,CloseBracket-OpenBracket-1); // returns 'System.string' // if multiple Generic parameters are present,they will be separated by commas... ... end; 将Generic参数解压缩为字符串后,如果需要访问该类型的RTTI,则可以使用TRttiContext.FindType(). 话虽如此,下面的代码提供了一堆RTTI助手: DSharp.Core.Reflection.pas(谷歌代码) DSharp.Core.Reflection.pas(BitBucket) 除此之外,它定义了一个TRttiTypeHelper类助手,它将一个GetGenericArguments()方法添加到TRttiType: TRttiTypeHelper = class helper for TRttiType ... public ... function GetGenericArguments: TArray<TRttiType>; ... end; 在内部,GetGenericArguments()使用我在上面提到的相同技术.有了它,你可以这样做: uses ...,System.Rtti,DSharp.Core.Reflection; var Ctx: TRttiContext; arr: TArray<TRttiType>; typ: TRttiType; s: string; ... begin ... arr := Ctx.GetType(TTestClass).GetField('test_list').FieldType.GetGenericArguments; typ := arr[0]; // returns RTTI for System.String s := typ.ToString; // returns 'System.string' ... end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |