5

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

4 回答 4

5

这是你要找的吗?

使用泛型和 RTTI 获取枚举字符串名称或枚举值

使用泛型/RTTI 单元系统进行枚举转换。RTTI 是跨平台的,包含一个用于将枚举转换为字符串并返回的类:TRttiEnumerationType

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

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

在这种情况下,TRttiEnumerationType 的泛型方法仅用于 Enums 而不是其他类类型,因为定义的功能是 Enum 特定的。

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

S := TRttiEnumerationType.GetName(D); 显示消息(S);从字符串转换回来也更简单。

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

于 2016-05-19T10:02:13.630 回答
4

您可以使用与 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;
于 2017-02-03T10:40:08.300 回答
3

您没有看到的是 TValue 的设计方式。它专门用作包含值的一种方式,而不是一种转换它们的方式。如您所说,如果您想在 srtings 和枚举之间进行转换,您已经知道如何进行了。使用 TypeInfo 中为此目的提供的函数。

于 2010-03-18T19:34:38.767 回答
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;
于 2010-03-18T20:02:27.547 回答