通过RTTI将TDateTime值传递给OleVariant属性

时间:2018-09-04 13:26:55

标签: datetime delphi rtti variant

当我使用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;

1 个答案:

答案 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。

报告为https://quality.embarcadero.com/browse/RSP-21176

相关问题