基于RTTI信息的Delphi调用方法

基于RTTI信息的Delphi调用方法,delphi,rtti,Delphi,Rtti,大家好,首先为我的英语不好道歉。 考虑下面的(不是实际的代码): 我正在使用RTTI设置“MyOtherClass”属性。对于string属性很简单,但我的问题是: 如何获取对“data”(MyClass)属性的引用,以便调用Go()方法 我想做这样的事情(伪代码): (如果这是C:() 注:这是在Delphi7中(我知道,甚至更糟)您可以通过调用getPropInfo(MyClass.ClassInfo)获得所有已发布属性的数组。这是一个PPropInfo指针数组。您可以通过调用PPropIn

大家好,首先为我的英语不好道歉。 考虑下面的(不是实际的代码):

我正在使用RTTI设置“MyOtherClass”属性。对于string属性很简单,但我的问题是:

如何获取对“data”(MyClass)属性的引用,以便调用
Go()
方法

我想做这样的事情(伪代码):

(如果这是C:()


注:这是在Delphi7中(我知道,甚至更糟)

您可以通过调用getPropInfo(MyClass.ClassInfo)获得所有已发布属性的数组。这是一个PPropInfo指针数组。您可以通过调用PPropInfo上的GetTypeData从中获取特定于类型的数据,这将返回一个PTypeData。它指向的记录将包含您要查找的有关类引用的信息。

如果string属性很简单,如您所说,那么我假设您正在调用
GetStrpopTypInfo
单元中选择code>和
SetStrProp
。使用
GetObjectProp
SetObjectProp
可以同样轻松地创建类类型属性

if Supports(GetObjectProp(Obj, 'data'), IMyInterface, Intf) then
  Intf.Go;
如果您确实不需要该接口,并且您知道
data
属性的类型为
TMyClass
,那么您可以更直接地执行以下操作:

(GetObjectProp(Obj, 'data') as TMyClass).Go;
这要求属性具有非null值

如果您不知道所需属性的名称,则可以使用
TypInfo
中的其他内容来搜索该属性。例如,以下函数将查找对象的所有已发布属性,这些属性的值实现
IMyInterface
;它对每个属性调用
Go
,没有特定顺序

procedure GoAllProperties(Other: TObject);
var
  Properties: PPropList;
  nProperties: Integer;
  Info: PPropInfo;
  Obj: TObject;
  Intf: IMyInterface;
  Unk: IUnknown;
begin
  // Get a list of all the object's published properties
  nProperties := GetPropList(Other.ClassInfo, Properties);
  if nProperties > 0 then try
    // Optional: sort the list
    SortPropList(Properties, nProperties);

    for i := 0 to Pred(nProperties) do begin
      Info := Properties^[i];
      // Skip write-only properties
      if not Assigned(Info.GetProc) then
        continue;

      // Check what type the property holds
      case Info.PropType^^.Kind of
        tkClass: begin
          // Get the object reference from the property
          Obj := GetObjectProp(Other, Info);
          // Check whether it implements IMyInterface
          if Supports(Obj, IMyInterface, Intf) then
            Intf.Go;
        end;

        tkInterface: begin
          // Get the interface reference from the property
          Unk := GetInterfaceProp(Obj, Info);
          // Check whether it implements IMyInterface
          if Supports(Unk, IMyInterface, Intf) then
            Intf.Go;
        end;
      end;
    end;
  finally
    FreeMem(Properties);
  end;
end;

RTTI在Delphi 2010中有了很大的改进。有一个简单易用的单元叫RTTI.pas。换句话说,切换到d2010,你会得到更少的痛苦。我很乐意这样做,Delphi中有很多很酷的新功能…但是在这个项目中我真的不能:/-但是我会尝试试用2010,只是为了看看它是如何工作的,并说服我的老板:D目前embarcadero正在德国进行路演。谢谢你,Rob,你的解决方案完美地解决了我的问题。这正是我想要的-你应该得到RTTI英雄徽章:)
(GetObjectProp(Obj, 'data') as TMyClass).Go;
procedure GoAllProperties(Other: TObject);
var
  Properties: PPropList;
  nProperties: Integer;
  Info: PPropInfo;
  Obj: TObject;
  Intf: IMyInterface;
  Unk: IUnknown;
begin
  // Get a list of all the object's published properties
  nProperties := GetPropList(Other.ClassInfo, Properties);
  if nProperties > 0 then try
    // Optional: sort the list
    SortPropList(Properties, nProperties);

    for i := 0 to Pred(nProperties) do begin
      Info := Properties^[i];
      // Skip write-only properties
      if not Assigned(Info.GetProc) then
        continue;

      // Check what type the property holds
      case Info.PropType^^.Kind of
        tkClass: begin
          // Get the object reference from the property
          Obj := GetObjectProp(Other, Info);
          // Check whether it implements IMyInterface
          if Supports(Obj, IMyInterface, Intf) then
            Intf.Go;
        end;

        tkInterface: begin
          // Get the interface reference from the property
          Unk := GetInterfaceProp(Obj, Info);
          // Check whether it implements IMyInterface
          if Supports(Unk, IMyInterface, Intf) then
            Intf.Go;
        end;
      end;
    end;
  finally
    FreeMem(Properties);
  end;
end;