将<t>类型的值转换为Variant,是否可能?</t>

时间:2011-10-25 15:55:26

标签: delphi generics delphi-2009 variant

这是一个片段,展示了我想要实现的目标:

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
var
  TmpValue: Variant;
begin
  TmpValue := Variant(Value); //Invalid typecast
  Result := VarType(TmpValue);
end;

我知道上面提到的使用类型转换是天真的,但我希望你能得到这个想法。我想用一些转换机制替换它。

TMyObject将始终是简单类型,如Integer,String,Single,Double。

这种转换的目的是函数VarType为每个我可以存储在其他地方的简单类型提供整数常量。

我想知道这种转换是否可行?

感谢您的时间。

4 个答案:

答案 0 :(得分:7)

在Delphis中,通过增强的RTTI(2010及更新版本)可以轻松解决这个问题。太糟糕了,你只限于2009年:(

function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Result := VarType(TValue.From<T>(Value).AsVariant);
end;

这仅适用于简单类型,但这是问题中指定的约束。

答案 1 :(得分:6)

您可以使用RTTI获取此信息,只需检查TTypeInfo.Kind属性的值:

检查此示例代码

{$APPTYPE CONSOLE}

uses
  TypInfo,
  Variants,
  Generics.Collections,
  SysUtils;

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Case PTypeInfo(TypeInfo(T))^.Kind of
    tkInteger : Result:=varInteger;
    tkFloat   : Result:=varDouble;
    tkString  : Result:=varString;
    tkUString : Result:=varUString;
    //add more types here
  End;
end;

Var
  LObj : TMyObject<Integer>;
begin
  try
     Writeln(VarTypeAsText(TMyObject<Integer>.Create.GetVarType(5)));
     Writeln(VarTypeAsText(TMyObject<String>.Create.GetVarType('Test')));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

这将返回

Integer
UnicodeString

答案 2 :(得分:1)

我看不出如何用泛型做到这一点。编译器需要知道可以为任何可能的TVariant类型的实例分配给T。你没办法告诉那个编译器是可能的。

如果这是C ++中的模板,那么它将是微不足道的。

答案 3 :(得分:1)

谢谢你的回答:

正如@RRUZ所示,它是可能的(我的意思是不是严格的分配,而是提取数据的类型)。我在等待任何答案的同时独自工作,并找到了更通用的解决方案。

所以我在这里定位:

type
  TMyObject<T> = class (TObject)
    function GetVarType(Value: T): TVarType;
  end;


function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
  Result := GetTypeData(TypeInfo(T)).varType;
end;

再次感谢!