开发者

Converting an string to a enum type using TValue?

I want to convert an string to an enum type using TValue, I googled but I didn't find how to do that.

type 
  TEnumTest = (etFirst, etSecond);

var 
  D: TEnumTest;
begin
  D := StrToENumTest('etFirst');
end;

function StrToEnumTest(pStr:String):TEnumTest;
var 
  V: TValue;
begin
  V := TValue.From<String>(pstr);
  Result := V.AsType<TEnumTest>;
end;

It doesn't work. That's must be something stupid I'm not seeing - but I didn't found it. What I made wrong?

I know how to use GetEnumValue.

EDIT: @Warren, it goes here as this is easier to post code:

  TEnumUtils = class
    class function GetAs<T>(pValor: String): T;
  end;

class function TEnumUtils.GetAs<T>(pValor: String): T;
var
  Tipo: PTypeInfo;
  Temp: Integer;
  PTemp: Pointer;

begin
   Tipo := TypeInfo(T);
   Temp := GetEnumValue(Tipo, pValor);
   PTemp := @Temp;
   Res开发者_开发技巧ult := T(PTemp^);
end;

Usage:

type 
  TEnumTest = (etFirst, etSecond);

var 
  D: TEnumTest;
begin
  D := TEnumUtils.GetAs<TEnumTest>('etFirst');
end;  


is this what you was looking for?

Using Generics & RTTI to get enum string name or enum value

Enum conversion with Generics / RTTI Unit System.RTTI is cross platform and contains a great class for converting enum to string and back: TRttiEnumerationType

The TRttiEnumerationType class has two class functions (methods you can call without creating an instance of the class) that clean up the code required from using the TypInfo methods. The easy reading version of these method declarations is:

class function GetName(AValue: T):string; class function GetValue(AName: string): T; Note these methods use Generics (thats the T bit). Generics are very cool as they allow you to write functionality once and then reuse it with different types at different times in code.

In this instance TRttiEnumerationType’s generic methods are for use with Enums only and not other class types as the functionality defined is specific for Enum’s.

To convert the TCompass enum now after adding RTTI to the uses would look like this.

S := TRttiEnumerationType.GetName(D); ShowMessage(S); To convert back from a string is also simpler.

D := TRttiEnumerationType.GetValue(S); How much easier is that to read! and as we have only had to declare the type once, we have less chance of silly copy paste errors in code.


You can use the same approach as it's write in the top of this page with GetEnumValue. You can easy declare a codeblock like this:

unit Unit3;

interface

uses
   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
   System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 
   typinfo, Vcl.StdCtrls;

   Type TMyEnumerator=(enm_Case0, enm_Case1, enm_Case2);

   Type TEnumConverter = class
   public
        class function EnumToInt<T>(const enValue: T): Integer;
        class function EnumToString<T>(enValue: T): string;
        class procedure StringToEnum<T>(strValue:String; var enValue:T);
   end;

implementation

class function TEnumConverter.EnumToInt<T>(const enValue: T): Integer;
begin
   Result := 0;
   Move(enValue, Result, sizeOf(enValue));
end;

class function TEnumConverter.EnumToString<T>(enValue: T): string;
begin
  Result := GetEnumName(TypeInfo(T), EnumToInt(enValue));
end;

 class procedure TEnumConverter.StringToEnum<T>(strValue: String; var enValue:T);
   var Tipo : PTypeInfo;
       Temp:Integer;
       PTemp : pointer;
begin
    Tipo := TypeInfo(T);
    Temp := GetEnumValue(Tipo, strValue);
    PTemp := @Temp;
    enValue := T(PTemp^);
end;

procedure TForm3.Button1Click(Sender: TObject);
   var s: String;
       v : TMyEnumerator;
begin
       { ************** Example *************** }

       showmessage(TEnumConverter.EnumToString(enm_Case1)); 

        s := 'enm_Case2';
        TEnumConverter.StringToEnum(s, v);

   case v of
     enm_Case0: showmessage('ok -> enm_Case0');
     enm_Case1: showmessage('ok -> enm_Case1');
     enm_Case2: showmessage('ok -> enm_Case2');
   end;

end;


What you're not seeing is the way TValue was designed. It's intended specifically as a way to contain values, not a way to convert them. If you want to convert between srtings and enums, as you said, you already know how. Use the functions provided for that purpose in TypeInfo.


So you know how to do this:

function StrToEnumTest(aStr:String):TEnumTest;
begin
  result := TEnumTest(GetEnumValue(TypeInfo(TEnumTest),aStr));
end;

But you don't want to do it that way? Why? I wish we could do this:

inline function StrToEnumTest(aStr:String):<T>;
begin
  result := <T>(GetEnumValue(TypeInfo(<T>),aStr));
end;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜