Search code examples
genericstypesdelphi-xe2

Generic type name and value


I have a Generic factory. I want to get the type name and its value as a string, eg:

An enumeration TTV with a value of Samsung would return 'TTV.Samsung'.

A string with a value of 'stackoverflow' would return 'string.stackoverflow'.

An integer with a value of 10 would return 'integer.10'.

A TValue made from TTV.Samsung (eg TValue.From(TTV.Samsung)) would return 'TTV.Samsung'.

Here is my function declaration:

function TGenericFactory<TKey>.GetTypeString(Key: TKey): string;

How do I make this work?


Solution

  • TValue has a ToString() method that handles the bulk of this work for you, so you can have your function create a temp TValue from any input value and then use TValue.ToString() to convert the value to a string regardless of what type it actually is. You can use RTTI to get the input value's type name. In the case where the input value is a TValue, you can use the RTTI of the type that the TValue is holding.

    uses
      System.Rtti;
    
    type
      TGenericFactory<TKey> = class
      public
        class function GetTypeString(Key: TKey): string;
      end;
    
    function TValueToString(const V: TValue): string; inline;
    begin
      Result := String(V.TypeInfo.Name) + '.' + V.ToString;
    end;
    
    class function TGenericFactory<TKey>.GetTypeString(Key: TKey): string;
    type
      PTValue = ^TValue;
    begin
      if TypeInfo(TKey) = TypeInfo(TValue) then
        Result := TValueToString(PTValue(@Key)^)
      else
        Result := TValueToString(TValue.From<TKey>(Key));
    end;
    

    Here are the results:

    type
      TTV = (Nokia, Samsung, Motorola);
    
    var
      S: String;
    begin
      S := TGenericFactory<TTV>.GetTypeString(TTV.Samsung);
      // returns 'TTV.Samsung'
    
      S := TGenericFactory<String>.GetTypeString('stackoverflow');
      // returns 'string.stackoverflow'
    
      S := TGenericFactory<Integer>.GetTypeString(10);
      // returns 'Integer.stackoverflow'
    
      S := TGenericFactory<TValue>.GetTypeString(TValue.From(TTV.Samsung));
      // returns 'TTV.Samsung'
    end.