为什么在VCL控件上调用TRttiContext.GetType时会重复某些属性? [英] Why are some properties repeated when TRttiContext.GetType is called on a VCL Control?

查看:84
本文介绍了为什么在VCL控件上调用TRttiContext.GetType时会重复某些属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么在调用TRttiContext.GetType时重复某些属性(例如 Action Align ),而另一些属性则不重复( AlignWithMargins )VCL控件?

Why are some properties repeated (such as Action and Align) where others are not (AlignWithMargins) when TRttiContext.GetType is called on a VCL Control?

uses
  System.RTTI,
  System.Generics.Collections,
  System.Generics.Defaults;

//....

procedure TForm11.btnShowPropertiesClick(Sender: TObject);
var
  R: TRttiContext;
  Props: TArray<TRttiProperty>;
  Prop : TRttiProperty;
begin
  memo1.Clear;
  R := TRttiContext.Create;
  Props := R.GetType(Sender.ClassType).GetProperties;

  //Sort properties by name
  TArray.Sort<TRttiProperty>(props,
    TComparer<TRttiProperty>.Construct(
      function(const Left, Right: TRttiProperty): Integer
      begin
        result := CompareText(Left.Name, Right.Name);
      end
    )
  );

  for prop in Props do
  begin
    try
      Memo1.Lines.Add(
         Prop.Name + ' : ' +
         Prop.PropertyType.ToString + ' = ' +
         Prop.GetValue(Sender).ToString);
    except
      Memo1.Lines.Add(Prop.Name + ' generated an exception');
    end;
  end;
end;

输出


Action : TBasicAction = (empty)
Action : TBasicAction = (empty)
Align : TAlign = alNone
Align : TAlign = alNone
AlignDisabled : Boolean = False
AlignWithMargins : Boolean = False
Anchors : TAnchors = [akLeft,akTop]
Anchors : TAnchors = [akLeft,akTop]
BiDiMode : TBiDiMode = bdLeftToRight
BiDiMode : TBiDiMode = bdLeftToRight
...

推荐答案

如果将 Prop.Parent.Name 添加到填充备忘录的循环中,则可以很容易地找到原因:/p>

If you would add Prop.Parent.Name to the loop that populates the memo you could have easily found out the cause:

for prop in Props do
begin
  try
    Memo1.Lines.Add(
       Prop.Parent.Name + '.' + { added }
       Prop.Name + ' : ' +
       Prop.PropertyType.ToString + ' = ' +
       Prop.GetValue(Sender).ToString);
  except
    Memo1.Lines.Add(Prop.Name + ' generated an exception');
  end;
end;

上面的代码产生:

TButton .Action:TBasicAction =(空)
TControl .Action:TBasicAction =(空)
TControl .Align:TAlign = alNone
TButton .Align:TAlign = alNone
TWinControl .AlignDisabled:布尔值= False
TControl .AlignWithMargins:布尔值= False
TControl .锚点:锚点= [akLeft,akTop]
TButton .锚点:锚点= [akLeft,akTop]
TButton .BiDiMode:TBiDiMode = bdLeftToRight
TControl .BiDiMode:TBiDiMode = bdLeftToRight
...

TButton.Action : TBasicAction = (empty)
TControl.Action : TBasicAction = (empty)
TControl.Align : TAlign = alNone
TButton.Align : TAlign = alNone
TWinControl.AlignDisabled : Boolean = False
TControl.AlignWithMargins : Boolean = False
TControl.Anchors : TAnchors = [akLeft,akTop]
TButton.Anchors : TAnchors = [akLeft,akTop]
TButton.BiDiMode : TBiDiMode = bdLeftToRight
TControl.BiDiMode : TBiDiMode = bdLeftToRight
...

现在您可以清楚地看到 GetProperties 枚举具有较高可见性或更改顺序的后代类中重新引入的属性.当 TCustomMyControl 定义具有 protected 可见性的 SomeProperty ,并且 TMyControl published 级别.

Now you can clearly see that that GetProperties enumerates properties that were reintroduced in descendant class with higher visibility or altered order. This is typical for controls when TCustomMyControl defines SomeProperty with protected visibility and TMyControl reintroduces it at published level.

您可以尝试在 TForm11 声明之前为 TButton 添加插入器类:

You can try adding interposer class for TButton before the TForm11 declaration:

type
  TButton = class(Vcl.StdCtrls.TButton)
  published
    property AlignWithMargins;
  end;

输出将反映更改.我添加了属性声明类型的完全限定名称( Prop.Parent.QualifiedName ),以使 TButton 来自我自己的单元更加明显.

The output would reflect the change. I added fully qualified name of property's declaring type (Prop.Parent.QualifiedName) to make it more obvious that TButton comes from my own unit.

Vcl.StdCtrls.TButton.Action:TBasicAction =(空)
Vcl.Controls.TControl.Action:TBasicAction =(空)
Vcl.Controls.TControl.Align:TAlign = alNone
Vcl.StdCtrls.TButton.Align:TAlign = alNone
Vcl.Controls.TWinControl.AlignDisabled:布尔值= False
Vcl.Controls.TControl.AlignWithMargins:布尔值= False
Unit1.TButton.AlignWithMargins:布尔值= False
Vcl.Controls.TControl.Anchors:TAnchors = [akLeft,akTop]
Vcl.StdCtrls.TButton.Anchors:TAnchors = [akLeft,akTop]
Vcl.StdCtrls.TButton.BiDiMode:TBiDiMode = bdLeftToRight
Vcl.Controls.TControl.BiDiMode:TBiDiMode = bdLeftToRight
...

Vcl.StdCtrls.TButton.Action : TBasicAction = (empty)
Vcl.Controls.TControl.Action : TBasicAction = (empty)
Vcl.Controls.TControl.Align : TAlign = alNone
Vcl.StdCtrls.TButton.Align : TAlign = alNone
Vcl.Controls.TWinControl.AlignDisabled : Boolean = False
Vcl.Controls.TControl.AlignWithMargins : Boolean = False
Unit1.TButton.AlignWithMargins : Boolean = False
Vcl.Controls.TControl.Anchors : TAnchors = [akLeft,akTop]
Vcl.StdCtrls.TButton.Anchors : TAnchors = [akLeft,akTop]
Vcl.StdCtrls.TButton.BiDiMode : TBiDiMode = bdLeftToRight
Vcl.Controls.TControl.BiDiMode : TBiDiMode = bdLeftToRight
...

这种行为不仅限于控件.在从祖先类重新引入属性的任何类中都可以观察到它.

This kind of behavior is not limited to controls. It can be observed on any class that reintroduces properties from an ancestor class.

这篇关于为什么在VCL控件上调用TRttiContext.GetType时会重复某些属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆