代码之家  ›  专栏  ›  技术社区  ›  Fabricio Araujo

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

  •  5
  • Fabricio Araujo  · 技术社区  · 15 年前

    我想使用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 回复  |  直到 8 年前
        1
  •  2
  •   Mason Wheeler    15 年前

    你看不到的是tValue的设计方式。它专门用来包含值,而不是转换值。如果您想在srtings和enum之间转换,如您所说,您已经知道如何转换了。使用typeinfo中为此目的提供的函数。

        2
  •  5
  •   Bahaa    9 年前

    这就是你要找的吗?

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

    使用generics/rtti unit system.rtti的枚举转换是交叉的 并包含一个用于将枚举转换为字符串和 返回:trttienumerationtype

    TrttiEnumerationType类有两个类函数(方法 可以在不创建类的实例的情况下调用)以清除 使用typinfo方法所需的代码。轻松阅读 这些方法声明的版本是:

    类函数getname(avalue:t):字符串;类函数 getValue(aname:string):t;注意,这些方法使用泛型(即 T位)。泛型非常酷,因为它们允许您编写 功能一次,然后使用不同类型的 代码中的时间。

    在本例中,使用的是TrttiEnumerationType_ 仅使用枚举而不使用其他类类型作为定义的功能 特定于枚举。

    在将rtti添加到uses之后立即转换tcompass枚举将 像这样。

    s:=trttienumerationtype.getname(d);showmessage(s);至 从字符串转换回来也比较简单。

    d:=trttienumerationtype.getvalue;简单多少 读起来了!因为我们只需要声明类型一次,所以我们 在代码中复制粘贴错误的可能性较小。

        3
  •  3
  •   F. Fabiano    8 年前

    您可以使用与使用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;
    
        4
  •  1
  •   Warren P    15 年前

    所以你知道怎么做:

    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;