Преобразование строки в тип enum с использованием TValue? - PullRequest
5 голосов
/ 18 марта 2010

Я хочу преобразовать строку в тип enum с помощью 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 ]

5 голосов
/ 19 мая 2016

это то, что вы искали?

Использование Generics & RTTI для получения имени строки enum или значения enum

Преобразование enum с помощью Generics / RTTI Unit System. RTT является перекрестным платформа и содержит отличный класс для преобразования enum в строку и обратно: TRttiEnumerationType

Класс TRttiEnumerationType имеет две функции класса (методы, которые вы можно вызвать, не создавая экземпляр класса), которые очищают код, необходимый для использования методов TypInfo. Легкое чтение версия этих объявлений методов:

функция класса GetName (AValue: T): строка; функция класса GetValue (AName: string): T; Обратите внимание, что эти методы используют Generics (вот Т бит). Дженерики очень крутые, так как позволяют писать функциональность один раз, а затем использовать его с разными типами на разных раз в коде.

В этом случае универсальные методы TRttiEnumerationType предназначены для использования. только с перечислениями, а не с другими типами классов в качестве определенной функциональности специфично для Enum.

Чтобы преобразовать перечисление TCompass теперь, после добавления RTTI к использованию, будет выглядеть так.

S: = TRttiEnumerationType.GetName (D); ShowMessage (S); к преобразовать обратно из строки также проще.

D: = TRttiEnumerationType.GetValue (S); Насколько легче что читать! и так как мы должны были объявить тип только один раз, мы меньше шансов на глупые ошибки копирования-вставки в коде.

3 голосов
/ 03 февраля 2017

Вы можете использовать тот же подход, который написан в верхней части этой страницы с помощью 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 голосов
/ 18 марта 2010

То, что вы не видите, это то, как TValue был разработан. Он предназначен специально для хранения значений, а не для их преобразования. Если вы хотите конвертировать srtings и enums, как вы сказали, вы уже знаете, как это сделать Используйте функции, предусмотренные для этой цели в TypeInfo.

1 голос
/ 18 марта 2010

Итак, вы знаете, как это сделать:

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;
...