在问题
here中,示出了用于创建与SetValue一起使用的兼容TValue的方法.我正在尝试制作一个通用版本,使用RTTI将类存储到INI文件中.这是我的减少代码:
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获取字符串中的值,然后再将其重新放回.我还没有找到一个很好的教程来解决这个问题.
解决方法
您必须在确定值之前获取TValue的实例以进行设置,然后使用GetEnumValue函数将字符串转换为枚举值
试试这段代码:
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,''); 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;