I use Delphi 10.3. I have two kind of method implementation for converting enumeration types back and fort to string. This is not the real implementation just two variants for the essence of the service:
Case 1:
TMyClass = class
private
ctx : TRTTIContext;
public
function asString<T>( const value_ : T ) : string;
function fromString<T>( const value_ : string ) : T;
end;
function TMyClass.asString<T>( const value_ : T ) : string;
var
rttiType : TRTTIType;
begin
rttiType := ctx.getType( typeInfo( T ) );
if ( rttiType.typeKind = tkEnumeration ) then
begin
result := TRTTIEnumerationType( rttiType ).getName( value_ );
end;
end;
function TMyClass.fromString<T>( const value_ : string ) : T;
var
rttiType : TRTTIType;
begin
rttiType := ctx.getType( typeInfo( T ) );
if ( rttiType.typeKind = tkEnumeration ) then
begin
result := TRTTIEnumerationType( rttiType ).getValue( value_ );
end;
end;
Case2:
IMyInterface<T> = interface
['{C03754B7-2225-4EB5-97C1-9820B3D1EBAD}']
function asString( const value_ : T ) : string;
function fromString( const value_ : string ) : T;
end;
TMyInterfaceImpl<T> = class ( TInterfacedObject, IMyInterface<T> )
private
ctx : TRTTIContext;
public
function asString( const value_ : T ) : string;
function fromString( const value_ : string ) : T;
end;
function TMyInterfaceImpl<T>.asString( const value_ : T ) : string;
var
rttiType : TRTTIType;
begin
rttiType := ctx.getType( typeInfo( T ) );
if ( rttiType.typeKind = tkEnumeration ) then
begin
result := TRTTIEnumerationType( rttiType ).getName( value_ );
end;
end;
function TMyInterfaceImpl<T>.fromString( const value_ : string ) : T;
var
rttiType : TRTTIType;
begin
rttiType := ctx.getType( typeInfo( T ) );
if ( rttiType.typeKind = tkEnumeration ) then
begin
result := TRTTIEnumerationType( rttiType ).getValue( value_ );
end;
end;
The TRTTIEnumeration.GetName/GetValue
works fine in TMyClass
implementation but does not compile in the TMyInterfaceImpl<T>
:
E2010 Incompatible types: 'System.Rtti.T' and 'MyInterfaceImpl.T'
E2531 Method 'GetValue' requires explicit type argument(s)
But I want to implement this service as an interface. Is there any solution to do that with the TMyInterfaceImpl<T>
? The generic type parameterized methods are not allowed in Interfaces. (procedure foo<T>( const value_ : T );
)
CodePudding user response:
GetName
and GetValue
class functions in TRTTIEnumerationType
are parameterized functions:
class function GetName<T{: enum}>(AValue: T): string; reintroduce; static;
class function GetValue<T{: enum}>(const AName: string): T; static;
You need to add T
when you call them GetName<T>(...)
and GetValue<T>(...)
function TMyInterfaceImpl<T>.asString( const value_ : T ) : string;
var
rttiType : TRTTIType;
begin
rttiType := ctx.getType( typeInfo( T ) );
if ( rttiType.typeKind = tkEnumeration ) then
begin
result := TRTTIEnumerationType( rttiType ).getName<T>( value_ );
end;
end;
function TMyInterfaceImpl<T>.fromString( const value_ : string ) : T;
var
rttiType : TRTTIType;
begin
rttiType := ctx.getType( typeInfo( T ) );
if ( rttiType.typeKind = tkEnumeration ) then
begin
result := TRTTIEnumerationType( rttiType ).getValue<T>( value_ );
end;
end;