質問hereには、SetValueで使用する互換性のあるTValueを作成する方法が示されています。私はRTTIを使用してINIファイルにクラスを格納するために、この汎用バージョンを作成しようとしています。これは私の削減コードです:参照の答えで列挙RTTIフィールドの一般的なTValueを作成するにはどうすればよいですか?
procedure TMyClass.LoadRTTI(xObject: TObject);
var
LContext: TRttiContext;
LClass: TRttiInstanceType;
xField : TRttiField;
szNewValue : String;
xValue : TValue;
begin
LContext := TRttiContext.Create;
LClass := LContext.GetType(xObject.ClassType) as TRttiInstanceType;
for xField in LClass.GetDeclaredFields do
begin
szNewValue := IniFile.ReadString(szSection, xField.Name, '');
if szNewValue <> '' then // emumerated will be '0' (zero) as that is what GetValue.AsString returns
begin
case xField.FieldType.TypeKind of
tkEnumeration: xValue := StrToIntDef(szNewValue, xField.GetValue(xObject).AsOrdinal);
end;
xField.SetValue(xObject, xValue); // FAILS HERE with 'Invalid calss typecast
end;
end;
end;
、解決策はTValue.From()メソッドを使用して値を取得することでしたが、それは適切な型の変数を必要とするように表示されます。私のコードはそれが何であるかわからないので、私はそのようなタイプがありません。
RTTIから文字列内の値を取得し、後でその値を戻す一般的な方法の例を探しています。私はまだこれをカバーする良いチュートリアルを発見していない。
ここprocedure TMyClass.LoadRTTI(xObject: TObject);
var
LContext: TRttiContext;
LClass: TRttiInstanceType;
xField : TRttiField;
szNewValue : String;
xValue : TValue;
begin
LContext := TRttiContext.Create;
LClass := LContext.GetType(xObject.ClassType) as TRttiInstanceType;
for xField in LClass.GetDeclaredFields do
begin
szNewValue := IniFile.ReadString(szSection, xField.Name, '');
if szNewValue <> '' then // emumerated will be '0' (zero) as that is what GetValue.AsString returns
begin
case xField.FieldType.TypeKind of
tkEnumeration:
begin
//get the instance to the TValue to set
xValue:=xField.GetValue(xObject);
//convert the data to a valid TValue
xValue:=TValue.FromOrdinal(xValue.TypeInfo,GetEnumValue(xValue.TypeInfo,szNewValue));
end;
end;
//assign the new value from the TValue
xField.SetValue(xObject, xValue);
end;
end;
end;
私の節約コードでは賢明ではなくなりました。 INIに保存する値を取得するには、xField.GetValue(xObject).ToString;を使用します。 – mj2008