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の使用方法を知っています。

編集:@ウォーレン、これはコードを投稿するのが簡単なので、ここに行きます:

  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

これはあなたが探していたものですか?

Generics&RTTIを使用して列挙型文字列名または列挙型値を取得する

Generics / RTTI Unit Systemを使用した列挙型変換。RTTIはクロスプラットフォームであり、列挙型を文字列に変換したり、元に戻したりするための優れたクラスが含まれています。TRttiEnumerationType

TRttiEnumerationTypeクラスには、TypInfoメソッドの使用に必要なコードをクリーンアップする2つのクラス関数(クラスのインスタンスを作成せずに呼び出すことができるメソッド)があります。これらのメソッド宣言の読みやすいバージョンは次のとおりです。

クラス関数GetName(AValue:T):string; クラス関数GetValue(AName:string):T; これらのメソッドはジェネリックス(つまりTビット)を使用することに注意してください。ジェネリックスは、機能を一度記述してから、コード内のさまざまな時点でさまざまなタイプで再利用できるため、非常に優れています。

この場合、TRttiEnumerationTypeのジェネリックメソッドは列挙型でのみ使用され、定義された機能は列挙型に固有であるため、他のクラスタイプでは使用されません。

RTTIを用途に追加した後、TCompass列挙型を今すぐ変換するには、次のようになります。

S:= TRttiEnumerationType.GetName(D); ShowMessage(S); 文字列から変換し直すのも簡単です。

D:= TRttiEnumerationType.GetValue(S); 読むのはとても簡単です!また、型を宣言する必要があるのは1回だけなので、コードでのばかげたコピー貼り付けエラーの可能性は低くなります。

于 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とenumsの間で変換したいのなら、あなたはすでにその方法を知っています。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 に答える