TControl(child)到TObject并通过RTTI或SetXXXXXXProperty设置其Parent属性

时间:2014-10-14 07:21:08

标签: delphi properties rtti

目前正在对delphi中的RTTI进行一些研究。

出现的问题如下。

对于这个例子,我有一个TPanel组件(从代码创建,所有者通过invoke方法传递)现在TPanel被强制转换为TObject(以保持我使用的通用方法)。

现在我尝试通过SetXXXXXXProp函数设置该属性(XXXXXX是以下任何一种(ord,variant,str,方法......基本上我尝试了所有的SetProperty函数。)

但由于一些奇怪的原因,我收到的消息是没有父属性。 如何设置父属性?

所以我希望你们中的任何一个人都能在正确的方向上给我一个“指针”。

class procedure TComponentsCreator.AddParent(obj, parent : TObject);
var
  count : integer;
  propList: PPropList;
  I: Integer;

  method : TMethod;
begin

  count := GetPropList(obj, propList);

  for I := 0 to count -1 do
    begin

      WriteLn(propList[i]^.Name);

      if (CompareStr(LowerCase(String(propList[i]^.Name)), LowerCase('Parent')) = 0) then
        begin
          SetObjectProp(obj, String(propList[i]^.Name), parent);
        end;
    end;
end;    

1 个答案:

答案 0 :(得分:1)

您正在使用专为.dfm流机制设计的旧式RTTI。当您调用GetPropList时,返回的列表包含已发布的属性。您正在寻找公开但尚未发布的Parent

您可以使用新样式RTTI来实现此目的,但这似乎是不必要的。当您在编译时不知道您希望操作的成员或类型时,需要RTTI。但是,您确实知道该成员。它是TControl.Parent。所以你可以写

(obj as TControl).Parent := parent;

如果由于某种原因,您觉得有必要使用RTTI,那么编写我能找到的代码的最简单方法是:

procedure SetControlParent(obj, parent: TObject);
var
  ctx: TRttiContext;
  typ: TRttiType;
  prop: TRttiProperty;
begin
  typ := ctx.GetType(obj.ClassType);
  prop := typ.GetProperty('Parent');
  prop.SetValue(obj, parent);
end;

我在这里省略了任何错误检查,但我希望你不会在实际代码中做同样的事情。


作为一个未成年人,你对CompareStr的呼吁是不必要的复杂。如果您希望使用不区分大小写的比较,请使用CompareText。如果您希望比较平等使用SameText。你可以更清楚地替换那些代码,就像这样:

if SameText(propList[I]^.Name, 'Parent') then