当我使用RTTI将TDateTime
值分配给对象的OleVariant
属性时,对象将成为Float值。
设计该对象是为了使此属性可以为Null或任何数据类型的值。如果变为浮动,则结果应计算为浮动差。如果它变成TDateTime
,则应将结果计算为两个TDateTime
值之差。
我应该直接将值传递给它,它将正常工作,但是中间有RTTI。
我知道TDateTime
在内部被表示为float,但是是否有可能准确接收我发送的数据类型?
请在以下代码示例中查看tkVariant
情况:
class procedure TRTTI.SetObjPropValue(obj: TObject; rprop: TRttiProperty; value: OleVariant);
var
rtyp: TRttiType;
vt: TVarType;
begin
if obj = nil then Exit();
if (rprop <> nil) and (rprop.IsWritable) then begin
case rprop.PropertyType.TypeKind of
tkInteger, tkInt64:
begin
value := TVarConv.NullableCurr(value);
if VarIsNumeric(value) then rprop.SetValue(obj, TValue.FromVariant(Trunc(value)));
end;
tkFloat:
begin
if rprop.PropertyType.Name = 'TDateTime' then
value := TVarConv.NullableDateTime(value)
else
value := TVarConv.NullableFloat(value);
if not VarIsNull(value) then rprop.SetValue(obj, TValue.FromVariant(value));
end;
tkChar, tkString, tkWChar, tkLString, tkWString, tkUString:
begin
rprop.SetValue(obj, TValue.FromVariant(VarToStr(value)));
end;
tkEnumeration:
begin
if rprop.PropertyType.Name = 'Boolean' then
value := TVarConv.NullableBool(value)
else
value := null;
if not VarIsNull(value) then rprop.SetValue(obj, TValue.FromVariant(value));
end;
tkVariant:
//Here I transmit the TDateTime value
rprop.SetValue(obj, TValue.FromVariant(value));
//An object receives Float
end;
end;
end;
答案 0 :(得分:5)
这里的问题是TValue.FromVariant
在内部“解包”通过的Variant
,将基础值存储在TValue
内。在您的情况下,它会适当地注意到TDateTime
中存储了一个Variant
,并将其存储为TDateTime
。
当您将包含TValue
(属于TypeKind TDateTime
)的tkFloat
向下传递到SetValue
的{{1}}时,它将转换为属性的类型为TRttiProperty
-请参见Variant
。此方法忽略了System.Rtti.Conv2Variant
可以是tkFloat
的事实,而只是将存储浮点数的TDateTime
放入结果中。
解决方案很简单:不使用Variant
,而只需使用TValue.FromVariant
。这样,您可以将Variant值存储在TValue中,并按原样传递它,而无需任何不必要的隐式类型转换到setter。