2010-03-18 125 views
3

我想使用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; 

回答

2

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

+0

是的,我知道。但我可以发誓,我已经看到有人使用TValue来做这件事。不管怎样,谢谢你。 – 2010-03-18 23:23:02

0

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

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; 
+0

Ts周围的尖括号只属于定义,而不属于函数体。 – 2010-03-18 20:30:09

+0

查看上面的修改。 – 2011-06-01 21:07:08

+0

@Warren P:请注意,当枚举被赋予不同的序数值时,Typeinfo将会丢失。在下一个枚举示例中,不可能使用GetEnumValue,并且将导致'E2134类型'TTestType'没有类型信息' 类型 TTestType =(ttTest1 = 2,ttTest2 = 4,ttTestUnknown = 6); 仅当枚举未被赋予任何序号值时才起作用。 – 2016-04-15 10:56:24

5

这是你在找什么?

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

枚举转换与泛型/ RTTI单位System.RTTI是跨平台 并包含一个伟大的类转换枚举字符串和 回:TRttiEnumerationType

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

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

在这种情况下TRttiEnumerationType的通用方法是使用 用枚举,而不是其他类类型定义 功能是具体的枚举的。

现在在将RTTI添加到使用后将TCompass枚举转换为 看起来像这样。

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

D:= TRttiEnumerationType.GetValue(S); 要读取多容易!并且由于我们只需要声明一次该类型,因此我们 在代码中出现愚蠢的复制粘贴错误的可能性较小。

1

您可以使用与使用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; 
相关问题