使用TRttiContext的属性名称;

时间:2015-04-16 14:52:13

标签: delphi delphi-xe2

我有以下课程,我希望从成员中获取一些名称,例如姓名

TInterface = interface(IXMLNode)
  function Get_One: Boolean;
  function Get_Two: Boolean;
  function Get_Three: Boolean;
  procedure Set_One(Value: Boolean);
  procedure Set_Two(Value: Boolean);
  procedure Set_Three(Value: Boolean);
  property One: Boolean read Get_One write Set_One;
  property Two: Boolean read Get_Two write Set_Two;
  property Three: Boolean read Get_Three write Set_Three;
end;

TTesting = class(TXMLNode, TInterface)
protected
  function Get_One: Boolean;
  function Get_Two: Boolean;
  function Get_Three: Boolean;
  procedure Set_One(Value: Boolean);
  procedure Set_Two(Value: Boolean);
  procedure Set_Three(Value: Boolean);
end;

获取名称我使用以下使用TRttiContext的方法

procedure getName();
var
  Ctx: TRttiContext;
  PropList: TArray<TRttiProperty>;
begin
  PropList := Ctx.GetType(TTesting).GetProperties;

 for i:= 0 to Length(PropList) do S1:= PropList[i].name; PropList[i].ToString;
.......

运行时,我总是有一个名为RefCount的项目。

我不应该得到值'一''两''三'?

2 个答案:

答案 0 :(得分:1)

除了TXMLNode继承的属性之外,您的类不包含任何属性。具体来说,它继承了公共属性TInterfacedObject.RefCount

虽然它实现了包含属性的接口,但类本身不包含属性。这是类定义:

type
  TTesting = class(TXMLNode, TInterface)
  protected
    function Get_One: Boolean;
    function Get_Two: Boolean;
    function Get_Three: Boolean;
    procedure Set_One(Value: Boolean);
    procedure Set_Two(Value: Boolean);
    procedure Set_Three(Value: Boolean);
  end;

您可以清楚地看到,那里没有声明属性。

其他一些评论:

  • 默认情况下,不会为受保护的成员生成RTTI。您需要使用$RTTI EXPLICIT指定受保护成员的RTTI,如最近所述:Call a protected method (constructor) via RTTI。如果您要在课程中添加属性,则可能需要使用$RTTI EXPLICIT PROPERTIES才能反映该属性。
  • 您的循环for i := 0 to Length(PropList)在数组末尾运行。循环至Length(...) - 1high(...)

答案 1 :(得分:0)

这里有很多问题。尽管在另一个答案中有详细说明,即使该类具有正确定义的属性,循环也是不正确的构造:

for i:= 0 to Length(PropList) do S1:= PropList[i].name; PropList[i].ToString;

这会贯穿所有项目加上一项,但最终只留下一个项目分配给S1(最后一项),这是你最初抱怨的。

现在,分配的PropList[i]恰好超出了列表的末尾,并且应该生成编译器警告,在循环结束后使用i,以及生成可能的运行时异常。

你也没有在任何地方定义S1,也不清楚它甚至在那里做了什么。

我注意到您在之前发表的评论中发布了同样错误的循环代码,并且没有得到解决。

我会显示正确的代码,但我不确定您到底想要完成的是什么,所以我会留下让您自己弄清楚的。但看起来应该更像这样:

for i:= 0 to Length(PropList) do 
begin
  S1:= PropList[i].name; // where is S1 being used?
  PropList[i].ToString;  // <-- this isn't doing anything
end;