unit Myc.Data.Types.Enum; interface uses System.SysUtils, System.Generics.Collections, Myc.Data.Types; type TDataEnumType = class(TInterfacedObject, IDataEnumType) private FName: string; FIdentifiers: TArray; FIdentifierMap: TDictionary; function GetName: String; function GetKind: TDataKind; function GetIdentifier(Idx: Integer): string; function GetIdentifierCount: Integer; function IndexOf(const AIdentifier: string): Integer; function CreateValue(const AValue: Integer): IDataEnumValue; overload; function CreateValue(const AIdentifier: string): IDataEnumValue; overload; public constructor Create(const AName: string; const AIdentifiers: array of string); destructor Destroy; override; end; implementation uses System.Rtti; type TDataEnumValue = class(TInterfacedObject, IDataEnumValue) private FDataType: IDataEnumType; FValue: Integer; function GetDataType: IDataType; function GetAsString: string; function GetValue: Integer; function AsTValue: TValue; public constructor Create(const ADataType: IDataEnumType; const AValue: Integer); end; { TDataEnumType } constructor TDataEnumType.Create(const AName: string; const AIdentifiers: array of string); var i: Integer; begin inherited Create; FName := AName; FIdentifierMap := TDictionary.Create; SetLength(FIdentifiers, Length(AIdentifiers)); for i := 0 to High(AIdentifiers) do begin if FIdentifierMap.ContainsKey(AIdentifiers[i]) then raise EArgumentException.CreateFmt('Duplicate identifier: %s', [AIdentifiers[i]]); FIdentifiers[i] := AIdentifiers[i]; FIdentifierMap.Add(AIdentifiers[i], i); end; end; destructor TDataEnumType.Destroy; begin FIdentifierMap.Free; inherited; end; function TDataEnumType.GetName: String; begin Result := FName; end; function TDataEnumType.GetKind: TDataKind; begin Result := dkEnum; end; function TDataEnumType.GetIdentifier(Idx: Integer): string; begin Result := FIdentifiers[Idx]; end; function TDataEnumType.GetIdentifierCount: Integer; begin Result := Length(FIdentifiers); end; function TDataEnumType.IndexOf(const AIdentifier: string): Integer; begin if not FIdentifierMap.TryGetValue(AIdentifier, Result) then Result := -1; end; function TDataEnumType.CreateValue(const AValue: Integer): IDataEnumValue; begin if (AValue < 0) or (AValue >= Length(FIdentifiers)) then raise EArgumentException.Create('Invalid enum value'); Result := TDataEnumValue.Create(Self, AValue); end; function TDataEnumType.CreateValue(const AIdentifier: string): IDataEnumValue; var idx: Integer; begin idx := IndexOf(AIdentifier); if idx < 0 then raise EArgumentException.CreateFmt('Unknown identifier: %s', [AIdentifier]); Result := CreateValue(idx); end; { TDataEnumValue } constructor TDataEnumValue.Create(const ADataType: IDataEnumType; const AValue: Integer); begin FDataType := ADataType; FValue := AValue; end; function TDataEnumValue.GetDataType: IDataType; begin Result := FDataType; end; function TDataEnumValue.GetAsString: string; begin Result := FDataType.Identifiers[FValue]; end; function TDataEnumValue.GetValue: Integer; begin Result := FValue; end; function TDataEnumValue.AsTValue: TValue; begin Result := TValue.From(FValue); end; end.