使用Typinfo单元,可以轻松枚举属性,如以下代码段所示:
procedure TYRPropertiesMap.InitFrom(AClass: TClass; InheritLevel: Integer = 0);
var
propInfo: PPropInfo;
propCount: Integer;
propList: PPropList;
propType: PPTypeInfo;
pm: TYRPropertyMap;
classInfo: TClassInfo;
ix: Integer;
begin
ClearMap;
propCount := GetPropList(PTypeInfo(AClass.ClassInfo), propList);
for ix := 0 to propCount - 1 do
begin
propInfo := propList^[ix];
propType := propInfo^.PropType;
if propType^.Kind = tkMethod then
Continue; // Skip methods
{ Need to get GetPropInheritenceIndex to work
if GetPropInheritenceIndex(propInfo) > InheritLevel then
Continue; // Dont include properties deeper than InheritLevel
}
pm := TYRPropertyMap.Create(propInfo.Name);
FList.Add(pm);
end; …Run Code Online (Sandbox Code Playgroud) 正如在Rtti数据处理和Delphi 2010中的一致性中已经讨论的那样,通过使用一对TRttiField和实例指针访问成员,可以达到原始数据和rtti值之间的一致性.对于只有基本成员类型(例如整数或字符串)的简单类,这将非常容易.但是,如果我们有结构化的字段类型呢?
这是一个例子:
TIntArray = array [0..1] of Integer;
TPointArray = array [0..1] of Point;
TExampleClass = class
private
FPoint : TPoint;
FAnotherClass : TAnotherClass;
FIntArray : TIntArray;
FPointArray : TPointArray;
public
property Point : TPoint read FPoint write FPoint;
//.... and so on
end;
Run Code Online (Sandbox Code Playgroud)
为了方便成员访问,我想构建一个成员节点树,它提供了一个获取和设置值,获取属性,序列化/反序列化值等的接口.
TMemberNode = class
private
FMember : TRttiMember;
FParent : TMemberNode;
FInstance : Pointer;
public
property Value : TValue read GetValue write SetValue; //uses FInstance
end;
Run Code Online (Sandbox Code Playgroud)
所以最重要的是获取/设置值,这是通过使用TRttiField的GetValue和SetValue函数完成的 - 如前所述.
那么FPoint成员的实例是什么?假设Parent是TExample类的Node,其中实例是已知的,成员是一个字段,那么Instance将是:
FInstance := Pointer …Run Code Online (Sandbox Code Playgroud) 我在使用rtti获取有关泛型类字段的信息时遇到了问题.经过一段时间的谷歌搜索后,我在QC中找到了一个描述该问题的条目.我的问题是,如果有人知道一个解决方法,或者这是否修复了Delphi XE2.以下是来自QC的重复该错误的源代码片段.
program Generics;
{$APPTYPE CONSOLE}
uses
Generics.Collections, Rtti, SysUtils;
type
TIntList = TList<Integer>;
TRecContainer = record
FList: TIntList;
end;
TObjContainer = class
FList: TIntList;
end;
var
ctx: TRttiContext;
f: TRttiField;
begin
ctx := TRttiContext.Create;
try
for f in ctx.GetType(TypeInfo(TRecContainer)).GetFields do
if f.FieldType <> nil then
writeln(f.FieldType.Name)
else
writeln('f.FieldType = nil');
for f in ctx.GetType(TypeInfo(TObjContainer)).GetFields do
if f.FieldType <> nil then
writeln(f.FieldType.Name)
else
writeln('f.FieldType = nil');
finally
ctx.Free;
readln;
end;
end.
Run Code Online (Sandbox Code Playgroud) 大家好:)这是我在stackoverflow的第一个问题:)
在Delphi XE2 RTTI中我们有TRttiMethod类,它具有CreateImplementation()动态创建过程或函数的功能,它具有相同的签名和与其正文相同的方法.
使用TRttiContext.getMethods()/ getMethod()我们可以获得类方法的集合 - TRttiMethod的集合.
文档说(http://docwiki.embarcadero.com/VCL/en/RTTI.TRttiMethod)不要直接创建TRTTiMethod,并使用getMethods()来获取其实例.
所以,如果我们有TRTTIMethod实例,我们可以动态创建具有相同签名的方法,并在以后调用它.
问题是..例如,我们有TNotifyEvent ... TRttiContext.getType(typeinfo(TNotifyEvent))返回TRttiType具有typekind =的实例对象tkMethod.我们知道TNotifyEvent的签名是对象的过程(sender:TObject);
有可能得到TRttiMethod这个吗?我想为事件动态创建eventHandler,TRttiMethod.CreateImplementation()
或者可能有另一种方法动态创建方法实现?
PS:想法是创建类似事件链的东西.在编译时,我们不知道事件类型/签名,因此我们可以使用泛型,如TEvenChain <TNotifyEvent>.Chain在已注册的事件处理程序上有集合,因为我们在编译时不知道处理程序类型,我们必须动态创建它,并且该处理程序只获取其参数并使用它们调用已注册的处理程序.
更新: 这里是一些代码(想法是创建事件处理程序链):
procedure TMainForm.FormCreate(Sender: TObject);
begin
FEventChain := TNotifyChain.Create();
FEventChain.AddHandler(event1);
FEventChain.AddHandler(event2);
TestButton.OnClick := FEventChain.EventHandler;
end;
Run Code Online (Sandbox Code Playgroud)
Event1&event2是(sender : TObject)形式的方法; 它不是一般示例(T在这种情况下是NotifyEvent/TChain <TNotifyEvent>)
TEventChain.EventHandler是TNotifyEvent太
TNotifyChain 是
TNotifyChain = class(TObject)
strict private
FEvent : TNotifyEvent;
FItems : TList<TNotifyEvent>;
FCtx : TRttiContext; …Run Code Online (Sandbox Code Playgroud) 我在Delphi XE,Windows 7中工作.
在应用程序中,我想为我的用户启用不同的报告类型以供选择.为此,我有一个基本报告类和每个报告类型的子类(xml,csv,ppt等).
{Just an illustrating example}
TBaseReport = class
public
constructor Create;
procedure GenerateReport; virtual; abstract;
class function ReportType: string; virtual; abstract;
end;
T*Report = class(TBaseReport);
//Etcetera.
Run Code Online (Sandbox Code Playgroud)
我想要做的是使用Rtti检测所有报告类并列出他们的ReportType.之后,我想使用Rtti创建所选报告类的实例并调用GenerateReport.总而言之,这并不难实现.
但是有一个主要的缺点:我从不硬编码使用降序类,因此代码不会包含在可执行文件中.
有没有一种不错的方法来强制链接器/编译器包含这些类?
一个(丑陋的)解决方法是在初始化部分模拟报告的使用,但我宁愿不这样做.更好的解决方案是使基类持久化并调用'RegisterClass(T*Report);' 在初始化部分.它有效,但我没有看到任何其他需要使它们持久化,所以再次,我宁愿不这样做.另一方面,也许这是唯一的方法吗?
提前致谢.
我曾问过一个问题C++ POD类型有RTTI吗?有人在评论中告诉我:
POD类型确实有type_info,但没有RTTI,这是可能的,因为type_info并不总是RTTI.
它似乎是正确的,因为我可以获得type_infoPOD(非多态)类型.
但是当我编译这个简单的程序时:
#include <iostream>
struct X
{
int a;
};
int main()
{
using namespace std;
std::cout << typeid(X) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
与-fno-rtti海湾合作委员会的旗帜:
$ g++ -fno-rtti main.cpp && ./main
Run Code Online (Sandbox Code Playgroud)
它不会编译:
main.cpp: In function ‘int main()’:
main.cpp:12:26: error: cannot use typeid with -fno-rtti
std::cout << typeid(X) << std::endl;
^
Run Code Online (Sandbox Code Playgroud)
这是否意味着type_info是RTTI的一部分,还是仅仅是GCC 的行为?
我正在使用优秀的Pascal DWScript整合内置脚本功能.我还使用以下命令将自己的Delphi端类定义(TDemo)添加到DWScript:
dwsUnit.ExposeRTTI( TDemo.ClassInfo )
Run Code Online (Sandbox Code Playgroud)
这只是工作,是快速添加属性和方法的好方法.
我也希望以类似的方式添加现有实例,因此我创建了类型为TDemo的实例FDemo,然后执行:
dwsUnit.ExposeInstanceToUnit( 'Demo', 'TDemo', FDemo );
Run Code Online (Sandbox Code Playgroud)
这看起来很有前途,但是我从未初始化的单位表中得到一个AV.我也查看了SVN源的单元测试代码,看看这个功能的使用但无济于事.任何人都可以指出我应该添加/更改的内容吗?
我有这门课:
TMyClass = class
public
function DoSomethingNice(const Value: string = 'Yes please!'): Boolean;
end;
Run Code Online (Sandbox Code Playgroud)
现在,使用RTTI,是否可以获取方法DoSomethingNice的参数值的默认值?如果是这样,怎么样?
我最感兴趣的是D2010解决方案,但XE也会这样做.
我正在使用属性检查器(例如JVCL库中的漂亮的JvInspector),它很好地让我查看和编辑我的类'TMyClass'的已发布属性.TMyClass来自TFrame并且有一些已发布的属性是我需要查看和编辑的唯一属性.当然TFrame有很多VCL属性,都是已发布的,我也看到了.
如何抑制祖先属性RTTI并留下我自己发布的属性?我正在使用XE3所以世界是我的牡蛎......也许吧.
我正在尝试了解TVirtualInterface类.
{$APPTYPE CONSOLE}
uses
SysUtils, Rtti;
type
ISpecificInterface = interface(IInvokable)
['{281D8B97-397E-430A-895A-9CA4E1F5FB5F}']
procedure SpecificProcedure;
end;
procedure AProcedure(Method: TRttiMethod; const Args: TArray<TValue>;
out Result: TValue);
begin
Writeln(Method.ToString);
end;
var
ISpecificInterfaceInstance: ISpecificInterface;
begin
ISpecificInterfaceInstance := TVirtualInterface.Create
(TypeInfo(ISpecificInterface), AProcedure) as ISpecificInterface;
ISpecificInterfaceInstance.SpecificProcedure;
end. // TVirtualInterface ref. counter is decremented
Run Code Online (Sandbox Code Playgroud)
在运行时实现接口有什么好处?
空间的用途是什么?
rtti ×10
delphi ×9
delphi-xe ×3
delphi-2010 ×2
properties ×2
c++ ×1
delphi-xe2 ×1
delphi-xe3 ×1
dwscript ×1
enumeration ×1
gcc ×1
oop ×1