如何为RTTI分配OleVariant? //将OleVariant或Variant转换为TValue并记住特定的TTypeKind或TRTTIType吗?

时间:2018-08-03 06:01:51

标签: delphi rtti variant spring4d

我有一个OleVariantVariant值,例如,它是用IXMLNode.GetAttributeNS读取的,使其成为“字符串”(varOleStr或{{1} }),我想用varString来写该值,要求TRTTIField.SetValue的分配与TValue兼容。

对于基本类型(沿TRTTIField.FieldType: TRTTITypeTVarType),而不是将每种情况都设为单独的情况:TRTTIType.TypeKind: TTypeKind,我在寻找一种从{{1}转换的通用方法}或case VarType(Value) and varTypeMask of varXXXX: ... endOleVariant,然后与特定的Variant分配兼容。

在Variant和RTTI世界之间转换值的方法是什么?

此外,如果有帮助,Spring4D库是项目的一部分。


更新:

从技术上讲,我正在以下代码中寻找TValue(在Variant世界中进行转换):

TRTTIType

我找到了VariantChangeTypeEx,但是,我不知道如何将Convert与它联系起来以使后续代码正常工作。 -我也不介意在RTTI世界中进行转换,而是以var Left: TRTTIField; Right: OleVariant; Temp: TValue; Instance: Pointer; begin { Examples: varOleStr --> varXXXX --> assignment-compatible TValue } Right := 'False'; // varOleStr, as read with IXMLNode.GetAttributeNS Right := Convert(Right, Left.FieldType); // making it possibly varBoolean Temp := TValue.FromVariant(Right); // tkEnumeration, like Left.FieldType.TypeKind Right := '2'; // varOleStr, as read with IXMLNode.GetAttributeNS Right := Convert(Right, Left.FieldType); // making it possibly varInteger Temp := TValue.FromVariant(Right); // tkInteger, like Left.FieldType.TypeKind Right := '3.1415'; // varOleStr, as read with IXMLNode.GetAttributeNS Right := Convert(Right, Left.FieldType); // making it possibly varDoiuble Temp := TValue.FromVariant(Right); // tkFloat, like Left.FieldType.TypeKind Right := 'Hello!'; // varOleStr, as read with IXMLNode.GetAttributeNS Right := Convert(Right, Left.FieldType); // making it possibly varOleStr Temp := TValue.FromVariant(Right); // tkUString, like Left.FieldType.TypeKind { ... and an assignment: } Left.SetValue(Instance, Temp); end; Left.FieldType)开始,然后以某种方式达到分配兼容性;因此Temp := TValue.FromVariant(Right)会变成tkUString给定的Temp.Kind / Boolean,tkEnumeration...。

如何使用RTTI分配变体?或者,如何将Variant转换为TValue,然后对其进行分配?

注意:如果字段类型和值类型的性质不同,RTTIField.SetValue将失败,并以tkFloat结束,因为RTTI不会尝试更改值的性质。我在这里的困难是要达到作业兼容性。


更新:给出答案后,以下代码概述了我的解决方案:

Left.FieldType.TypeKind

2 个答案:

答案 0 :(得分:3)

TValue中的内置类型强制转换在这里无济于事,因为它们只允许那些显式兼容(即可分配)的类型。从技术上讲,如果您将Variant存储在TValue中而没有“拆包”,这就是FromVariant内部所做的事情,则它应该能够将Variant强制转换为通常可以强制转换/转换为的任何变量。但是,将变量“ True”或“ False”强制转换为布尔值至少有一个问题(请参见https://quality.embarcadero.com/browse/RSP-20160

但是,由于您已经在使用Spring4D,因此可以使用其改进的TValue类型转换功能。

只需使用ConvertTValueHelper中的Spring.pas方法。

您可以在其中传递PTypeInfo(在代码中为Left.FieldType.Handle)和可选的TFormatSettings-默认情况下,它将使用当前语言环境。

答案 1 :(得分:2)

  

在Variant和RTTI世界之间转换值的方法是什么?

System.RTTI.TValue中使用内置的类函数转换:

myTValue := TValue.FromVariant(myVariant);
  

从Variant值构建新的TValue记录。

     

FromVariant 是一种静态方法,可用于构建具有存储的Variant值的TValue记录。 Value参数包含将存储在内置TValue记录内的Variant。