uses
TypInfo, SysUtils, SysConst;
type
TEnumHelper = record
class function TryGetEnumName<T: record>(Value: T; out S: String): Boolean; static;
class function GetEnumName<T: record>(Value: T): String; static;
class function TryGetEnumValue<T: record>(const Name: String; out Enum: T): Boolean; overload; static;
class function GetEnumValue<T: record>(const Name: String): T; overload; static;
class function TryGetEnumValue<T: record>(Value: Integer; out Enum: T): Boolean; overload; static;
class function GetEnumValue<T: record>(Value: Integer): T; overload; static;
end;
class function TEnumHelper.TryGetEnumName<T>(Value: T; out S: String): Boolean;
var
P: PTypeInfo;
IValue: Integer;
begin
Result := False;
S := '';
P := TypeInfo(T);
if (P = nil) or (P^.Kind <> tkEnumeration) then
begin
Exit;
end;
IValue := 0;
Move(Value,IValue,SizeOf(T));
S := TypInfo.GetEnumName(P,IValue);
Result := True;
end;
class function TEnumHelper.GetEnumName<T>(Value: T): String;
var
P: PTypeInfo;
IValue: Integer;
begin
P := TypeInfo(T);
if (P = nil) or (P^.Kind <> tkEnumeration) then
begin
raise EInvalidOpException.CreateRes(@SVarNotImplemented);
end;
IValue := 0;
Move(Value,IValue,SizeOf(T));
Result := TypInfo.GetEnumName(P,IValue);
end;
class function TEnumHelper.TryGetEnumValue<T>(const Name: String; out Enum: T): Boolean;
var
P: PTypeInfo;
IValue: Integer;
begin
Result := False;
Enum := Default(T);
P := TypeInfo(T);
if (P = nil) or (P^.Kind <> tkEnumeration) then
begin
Exit;
end;
IValue := TypInfo.GetEnumValue(P,Name);
with GetTypeData(P)^ do
begin
if (IValue < MinValue) or (IValue > MaxValue) then
begin
Exit;
end;
end;
Move(IValue,Enum,SizeOf(T));
Result := True;
end;
class function TEnumHelper.GetEnumValue<T>(const Name: String): T;
var
P: PTypeInfo;
IValue: Integer;
begin
Result := Default(T);
P := TypeInfo(T);
if (P = nil) or (P^.Kind <> tkEnumeration) 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;
end;
Move(IValue,Result,SizeOf(T));
end;
class function TEnumHelper.TryGetEnumValue<T>(Value: Integer; out Enum: T): Boolean;
var
P: PTypeInfo;
begin
Result := False;
Enum := Default(T);
P := TypeInfo(T);
if (P = nil) or (P^.Kind <> tkEnumeration) then
begin
Exit;
end;
with GetTypeData(P)^ do
begin
if (Value < MinValue) or (Value > MaxValue) then
begin
Exit;
end;
end;
Move(Value,Enum,SizeOf(T));
Result := True;
end;
class function TEnumHelper.GetEnumValue<T>(Value: Integer): T;
var
P: PTypeInfo;
begin
Result := Default(T);
P := TypeInfo(T);
if (P = nil) or (P^.Kind <> tkEnumeration) then
begin
raise EInvalidOpException.CreateRes(@SVarNotImplemented);
end;
with GetTypeData(P)^ do
begin
if (Value < MinValue) or (Value > MaxValue) then
begin
raise ERangeError.CreateRes(@SRangeError);
end;
end;
Move(Value,Result,SizeOf(T));
end;
こんな感じで使います。var
S: String;
begin
if TEnumHelper.TryGetEnumName(0,S) = True then // Error (0 is not enumeration)
begin
Label1.Caption := S;
end
else
begin
Label1.Caption := '(Error)';
end;
S := TEnumHelper.GetEnumName(taLeftJustify); // taLeftJustify -> 'taLeftJustify'
Label2.Caption := S;
S := TEnumHelper.GetEnumName(False); // False -> 'False'
Label3.Caption := S;
end;
元ねたはDelphi XE2 Foundations。→列挙型と列挙子名(文字列)または整数の相互変換(ジェネリックス版) (Gist)
0 件のコメント:
コメントを投稿