使用TValue将字符串转换为枚举类型?

时间:2010-03-18 18:46:41

标签: delphi delphi-2010 rtti tvalue

我想使用TValue将字符串转换为枚举类型,我用谷歌搜索但我没有找到如何做到这一点。

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;

它不起作用。那一定是我看不到的傻事 - 但我没有 找到了。我做错了什么?

我知道如何使用GetEnumValue。

编辑:@Warren,因为这更容易发布代码:

  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;
   Result := T(PTemp^);
end;

用法:

type 
  TEnumTest = (etFirst, etSecond);

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

4 个答案:

答案 0 :(得分:5)

这就是你要找的东西吗?

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

  

使用Generics / RTTI Unit System.RTTI进行枚举转换   平台,包含一个很好的类,用于将枚举转换为字符串和   back:TRttiEnumerationType

     

TRttiEnumerationType类有两个类函数(方法你   可以调用而无需创建类的实例)来清理   使用TypInfo方法所需的代码。易读   这些方法声明的版本是:

     

类函数GetName(AValue:T):string;阶级功能   GetValue(AName:string):T;注意这些方法使用泛型(即   T位)。泛型非常酷,因为它们允许你写   功能一次,然后在不同的类型重用它   代码中的时间。

     

在这种情况下,TRttiEnumerationType的泛型方法可供使用   仅使用Enums而不是其他类类型作为定义的功能   是针对Enum的。

     

在将RTTI添加到用途后,立即转换TCompass枚举   看起来像这样。

     

S:= TRttiEnumerationType.GetName(D); ShowMessage(S);至   从字符串转换回来也更简单。

     

D:= TRttiEnumerationType.GetValue(S);多么容易   那要读!因为我们只需要声明一次类型,我们   在代码中愚蠢地复制粘贴错误的可能性较小。

答案 1 :(得分:3)

您可以使用与使用GetEnumValue在本页顶部编写相同的方法。您可以轻松声明如下代码块:

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;

答案 2 :(得分:2)

你没有看到的是TValue的设计方式。它专门用作包含值的方法,而不是转换它们的方法。如果你想在srtings和enums之间进行转换,就像你说的那样,你已经知道了。在TypeInfo中使用为此目的提供的功能。

答案 3 :(得分:1)

所以你知道如何做到这一点:

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

但你不想这样做吗?为什么?我希望我们能做到这一点:

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