ずいぶん前に列挙型の値と列挙子の名前を相互変換する方法について取り上げましたが、これを関数化しようとすると結局のところ必要な列挙型すべてについて個別に実装の必要がありました。ところが
Lynaたんさん(talesさん)の
ジェネリクスを使って少しだけ手軽に列挙型の値を文字列に変換する。 - 全力わはーではDelphi 2009の新機能の
ジェネリックスを利用することでこれを単一の実装で実現しています。ということでLynaたんさんが提示した手法で列挙型と列挙子名の相互変換を関数化してみました(単なるパクリですいません)。ここではクラスではなく
高度なレコード型を使用します。またジェネリックスを使いますので当然のことながらDelphi 2009以降でのみ有効です。
uses
TypInfo, SysUtils, SysConst;
type
TEnumHelper = record
class function GetEnumName<T>(Value: T): String; static;
class function GetEnumValue<T>(const Name: String): T; static;
end;
class function TEnumHelper.GetEnumName<T>(Value: T): String;
var
P: PTypeInfo;
IValue: Integer;
begin
P := TypeInfo(T);
if P = nil then
begin
raise EInvalidOpException.CreateRes(@SVarNotImplemented);
end;
IValue := 0;
Move(Value,IValue,SizeOf(T));
Result := TypInfo.GetEnumName(P,IValue);
end;
class function TEnumHelper.GetEnumValue<T>(const Name: String): T;
var
P: PTypeInfo;
IValue: Integer;
begin
P := TypeInfo(T);
if P = nil then
begin
raise EInvalidOpException.CreateRes(@SVarNotImplemented);
end;
IValue := TypInfo.GetEnumValue(P,Name);
with GetTypeData(P)^ do
begin
if (IValue < MinValue) or (IValue > MaxValue) then
begin
raise ERangeError.CreateRes(@SRangeError);
end;
Result := Default(T);
Move(IValue,Result,SizeOf(T));
end;
end;
TEnumHelper.GetEnumNameの型パラメータは省略可能です(引数の型から自動的に推論されます)が、TEnumHelper.GetEnumValueについては型パラメータが必須となります。
var
Alignment: TAlignment;
begin
Alignment := TEnumHelper.GetEnumValue<TAlignment>('taLeftJustify');
end;
var
S: String;
begin
S := TEnumHelper.GetEnumName(taLeftJustify);
end;
こんな感じで使うことができます。
0 件のコメント:
コメントを投稿