为什么在VCL控件上调用TRttiContext.GetType时会重复某些属性? [英] Why are some properties repeated when TRttiContext.GetType is called on a VCL Control?
问题描述
为什么在调用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屋!