我正在使用Delphi Seattle Update1 Win64並嘗試使用RTTI提取屬性。我的目標是將組件屬性序列化爲JSON,因爲我需要在非Delphi環境中使用此信息。GetPropList與TRectangle返回StrokeThickness作爲屬性應該是Stroke類的一部分
我的問題是關於GetPropList
爲TRectangle
(例子),以及爲什麼它返回則不能傳遞到GetPropValue
,即性質:
StrokeThickness
類型tkFloat
StrokeCap
類型tkEnumeration
StrokeDash
作爲類型tkEnumeration
StrokeJoin
as type tkEnum關合作。
GetPropList
不正確地爲tkClass
類型,這是我本來期望,並返回Stroke
解析時,Stroke類回報Thickness
,Cap
,Dash
和Join
,我可以得到這些正確的價值觀。
問題是執行GetPropValue
StrokeThickness
會導致異常。因此,我必須特別注意GetPropList
返回的「破損」屬性,我想避免這種情況。
起初我還以爲這是與GetPropList返回屬性的問題根本不存在,但我可以執行以下代碼,他們都工作:
Rectangle1.StrokeThickness := 5; //works
Rectangle1.Stroke.Thickness := 10; //and also works
型tkFloat或tkEnumeration工作的其他屬性預計並返回正確的值。
我創建了一個小測試應用程序來嘗試調試這個。我發現在StrokeThickness的情況下,M.Code在函數System.TypeInfo.TPropSet.GetProp(行2397)中爲零,我想解釋爲什麼會導致異常。
附加的是我創建的測試代碼,用於確認我在更大的項目中看到的內容。我將如何處理上面列出的四個屬性而無需特殊情況。
形式:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 202
ClientWidth = 542
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object Rectangle1: TRectangle
Position.X = 40.000000000000000000
Position.Y = 40.000000000000000000
Size.Width = 97.000000000000000000
Size.Height = 97.000000000000000000
Size.PlatformDefault = False
end
object StrokeThickness: TButton
Position.X = 40.000000000000000000
Position.Y = 144.000000000000000000
Size.Width = 97.000000000000000000
Size.Height = 22.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Text = 'RTTI'
OnClick = StrokeThicknessClick
end
object Memo1: TMemo
Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
DataDetectorTypes = []
Position.X = 152.000000000000000000
Position.Y = 40.000000000000000000
Size.Width = 353.000000000000000000
Size.Height = 129.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
Viewport.Width = 349.000000000000000000
Viewport.Height = 125.000000000000000000
end
end
測試代碼:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.Edit, FMX.Objects, FMX.ScrollBox, FMX.Memo;
type
TForm1 = class(TForm)
Rectangle1: TRectangle;
StrokeThickness: TButton;
Memo1: TMemo;
procedure StrokeThicknessClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses System.TypInfo;
{$R *.fmx}
procedure TForm1.StrokeThicknessClick(Sender: TObject);
var
vValue : String;
PropList : PPropList;
PropInfo : PPropInfo;
PropType : PPTypeInfo;
PropListCount : Integer;
I: Integer;
begin
memo1.Lines.Clear;
PropListCount := GetPropList(Rectangle1, PropList);
for I := 0 to PropListCount-1 do
begin
PropInfo := PropList^[I];
PropType := PropInfo^.PropType;
Memo1.Lines.Add('Name: '+String(PropInfo^.Name));
Memo1.Lines.Add('PropType: '+String(PropInfo^.PropType^.Name));
Memo1.Lines.Add('PropKind: '+GetEnumName(TypeInfo(TTypeKind), Ord(PropType^.Kind)));
Memo1.Lines.Add('');
end;
vValue := GetPropValue(Rectangle1, 'Name'); //test string
Memo1.Lines.Add('Proprty Name = '+VarToStr(vValue));
vValue := GetPropValue(Rectangle1, 'Height'); //test float
Memo1.Lines.Add('Property Height = '+VarToStr(vValue));
vValue := GetPropValue(Rectangle1, 'Sides'); //test enumeration
Memo1.Lines.Add('Property Sides = '+VarToStr(vValue));
//The following would cause an exception
{
vValue := GetPropValue(Rectangle1, 'StrokeThickness');
Memo1.Lines.Add('Property StrokeThickness ='+VarToStr(vValue));
}
Rectangle1.StrokeThickness := 5; //works ??
//Still fails after it was explicitly set
{
vValue := GetPropValue(Rectangle1, 'StrokeThickness');
Memo1.Lines.Add('Property StrokeThickness ='+VarToStr(vValue));
}
Rectangle1.Stroke.Thickness := 10; //and also works... as expected
//The following with cause an exception
{
vValue := GetPropValue(Rectangle1, 'StrokeDash');
Memo1.Lines.Add('StrokeDash = '+VarToStr(vValue));
}
end;
end.
文件的錯誤報告用[QualityPortal](HTTP://quality.embarcadero .com),然後嘗試從'System.Rtti'單元切換到新樣式的RTTI,而不是使用'System.TypInfo'單元中的舊式RTTI,看看它是否在同一個屬性上崩潰。 –
@RemyLebeau謝謝;會做。很高興在我提交錯誤之前得到確認我沒有做錯某些形式更好的人。我將用'System.Rtti'進行分叉和測試,但是我讀到它膨脹了代碼大小,所以我用'System.TypInfo'代替。我會比較一下,看看是否有任何影響。 – lowrider
我不確認或否認這是否是一個錯誤,因爲我還沒有機會自己嘗試。但它聽起來像一個錯誤,報告它並沒有什麼壞處,你可以隨時關閉它。 –