Beispiel:
[delphi]var
S: string;
E: TFloatValue;
begin
E := fvCurrency;
S := RTTIServices.EnumToStr<TMyEnum>(E);
ShowMessage(S);
E := RTTIServices.StrToEnum<TMyEnum>(S);[/delphi]
Der Code:
[delphi]uses
SysConst, RTLConsts, SysUtils, StrUtils, TypInfo, RTTI;
type
/// <summary>
/// Kleine Sammlung an RTTI-Helferlein.
/// </summary>
RTTIServices = class
private
class function CheckEnumType<T>(EType: TTypeKind; CodePos: string): Integer; static; inline;
public
class function SetToStr<TSet>(Value: TSet; Brackets: Boolean=True): string; static;
class function StrToSet<TSet>(Value: string): TSet; static;
class function EnumToStr<TEnum>(Value: TEnum): string; static;
class function StrToEnum<TEnum>(Value: string): TEnum; static;
end;
class function RTTIServices.CheckEnumType<T>(EType: TTypeKind; CodePos: string): Integer;
begin
Result := SizeOf(T);
if (PTypeInfo(TypeInfo(T)).Kind <> EType) or not (Result in [1, 2, 4]) then
raise EInvalidCast.Create(CodePos + ‚: ‚ + LoadResString(@SInvalidCast) + ‚ (‚ + PTypeInfo(TypeInfo(T)).Name + ‚)‘);
end;
class function RTTIServices.EnumToStr<TEnum>(Value: TEnum): string;
begin
case CheckEnumType<TEnum>(tkEnumeration, ClassName + ‚.EnumToStr‘) of
1: Result := GetEnumName(PTypeInfo(TypeInfo(TEnum)), PByte(@Value)^);
2: Result := GetEnumName(PTypeInfo(TypeInfo(TEnum)), PWord(@Value)^);
else Result := GetEnumName(PTypeInfo(TypeInfo(TEnum)), PInteger(@Value)^);
end;
end;
class function RTTIServices.SetToStr<TSet>(Value: TSet; Brackets: Boolean): string;
begin
case CheckEnumType<TSet>(tkSet, ClassName + ‚.SetToStr‘) of
1: Result := SetToString(PTypeInfo(TypeInfo(TSet)), PByte(@Value)^, Brackets);
2: Result := SetToString(PTypeInfo(TypeInfo(TSet)), PWord(@Value)^, Brackets);
else Result := SetToString(PTypeInfo(TypeInfo(TSet)), PInteger(@Value)^, Brackets);
end;
end;
class function RTTIServices.StrToEnum<TEnum>(Value: string): TEnum;
begin
case CheckEnumType<TEnum>(tkEnumeration, ClassName + ‚.StrToEnum‘) of
1: PByte(@Value)^ := GetEnumValue(PTypeInfo(TypeInfo(TEnum)), Value);
2: PWord(@Value)^ := GetEnumValue(PTypeInfo(TypeInfo(TEnum)), Value);
else PInteger(@Value)^ := GetEnumValue(PTypeInfo(TypeInfo(TEnum)), Value);
end;
end;
class function RTTIServices.StrToSet<TSet>(Value: string): TSet;
begin
case CheckEnumType<TSet>(tkSet, ClassName + ‚.StrToSet‘) of
1: PByte(@Value)^ := StringToSet(PTypeInfo(TypeInfo(TSet)), Value);
2: PWord(@Value)^ := StringToSet(PTypeInfo(TypeInfo(TSet)), Value);
else PInteger(@Value)^ := StringToSet(PTypeInfo(TypeInfo(TSet)), Value);
end;
end;[/delphi]
Hallo himitsu-san,
habe diese Geheimniswelten durch eine grosse Suchmaschine trotzdem finden können. Wir haben in der Delphipraxis hier http://www.delphipraxis.net/180700-set-enumeration-type-datenbank-parameter-zuweisen.html mal drüber diskutiert. Deine Lösung finde ich gut und würde sie gerne verwenden. Darf ich?
Allerdings ist ein kleiner vermutlich Copy&Paste Fehler im obigen Code – EnumToStr muss auf tkEnumeration prüfen, nicht auf tkSet.
Böses C&P 👿
Aber genau darum die generischen Funktionen, auch wenn sie etwas mehr Overhead erzeugen, als der direkte Aufruf, damit man nur einmal aufpassen und sich dann nie wieder Gedanken machen muß.