Reputation: 6979
here is a snippet showing what I am trying to achieve:
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;
I know that above apporach with typecast is naive but I hope you get the idea. I would like to replace it with some conversion mechanism.
TMyObject will be always of simple type like Integer, String, Single, Double.
The purpose of such conversion is that function VarType gives me integer constant for each simple type which I can store somewhere else.
I would like to know if such conversion is possible?
Thanks for your time.
Upvotes: 6
Views: 4242
Reputation: 26830
It's trivially solvable in Delphis with enhanced RTTI (2010 and newer). Too bad you're limited to 2009 :(
function TMyObject<T>.GetVarType(Value: T): TVarType;
begin
Result := VarType(TValue.From<T>(Value).AsVariant);
end;
This works only for simple types but that was a constraint specified in the question.
Upvotes: 7
Reputation: 6979
Thanks guys for your answers:
As @RRUZ have shown it is possible (I mean not strict assigment but extracting the type of data). I was working on my own while waiting for any answer and have found a more generic solution.
So I am positing it here:
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;
Once again thanks!
Upvotes: 1
Reputation: 136391
You can use the RTTI to get this info, just check the value of the TTypeInfo.Kind
property:
Check this sample code
{$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.
this will return
Integer
UnicodeString
Upvotes: 6
Reputation: 612954
I can't see how it could be possible to do this with generics. The compiler needs to know that an instance of type T
can be assigned to a Variant
for any possible T
. There's no way for you to tell that compiler that is possible.
If this were templates as in C++ then it would be trivial.
Upvotes: 1