2013-05-08 2 views
2

Я знаю, как получить значение перечисления из целого значения, и у меня есть этот кодДельф - как получить тип перечисления

function GetEnumValue(intValue:integer):TMyType 
begin 
    if(ordValue >= Ord(Low(TMyType)))and(ordValue <= Ord(High(TMyType)))then 
     result :=TMyType(ordValue) 
    else 
     raise Exception.Create('ordValue out of TMyType range'); 
end; 

Я имею похожий код, как выше во многих местах для многих типов перечислений кроме TMyType , Я хочу инкапсулировать этот код в один защищенный код на базовый класс, поэтому унаследованный класс может его использовать.

но я не знаю, как обобщить TMyType, так что мой код может проверить, если это правильно перечисление или другой тип объекта

Я не могу иметь понятия, что такое перечисление базового класса (как TObject для всех типов объектов или TControl для всех типов VCL), то я могу проверить, как этот код

+1

Какая версия Delphi? –

ответ

4

Нет такой вещи, как базовый тип для типа перечисления, например, TObject является базой для классов.

Если у вас есть версия Delphi, которая поддерживает общие функции, вы можете использовать следующий помощник, чтобы сделать общий набор от порядкового значения до значения перечисления.

uses 
    System.SysUtils,TypInfo; 

Type 
    TEnumHelp<TEnum> = record 
    type 
    ETEnumHelpError = class(Exception); 
    class function Cast(const Value: Integer): TEnum; static; 
    end; 

class function TEnumHelp<TEnum>.Cast(const Value: Integer): TEnum; 
var 
    typeInf : PTypeInfo; 
    typeData : PTypeData; 
begin 
    typeInf := PTypeInfo(TypeInfo(TEnum)); 
    if (typeInf = nil) or (typeInf^.Kind <> tkEnumeration) then 
    raise ETEnumHelpError.Create('Not an enumeration type'); 
    typeData := GetTypeData(typeInf); 
    if (Value < typeData^.MinValue) then 
    raise ETEnumHelpError.CreateFmt('%d is below min value [%d]',[Value,typeData^.MinValue]) 
    else 
    if (Value > typeData^.MaxValue) then 
    raise ETEnumHelpError.CreateFmt('%d is above max value [%d]',[Value,typeData^.MaxValue]); 
    case Sizeof(TEnum) of 
    1: pByte(@Result)^ := Value; 
    2: pWord(@Result)^ := Value; 
    4: pCardinal(@Result)^ := Value; 
    end; 
end; 

Пример:

Type 
    TestEnum = (aA,bB,cC); 

var 
    e : TestEnum; 
... 
e := TEnumHelp<TestEnum>.Cast(2); // e = cC 

Существует одно ограничение:

Перечисления, которые несмежных или не начинается с нуля, не имеют RTTI TypeInfo информации. См. RTTI properties not returned for fixed enumerations: is it a bug?.

+0

вы экономите мой день ... спасибо большое ... что я ищу, так трудно найти ссылку, как это, и мне повезло, я использую XE2 – navirius

+0

Я бы сделал метод Cast общим, а не тип. –

+0

@StefanGlienke, вы имеете в виду 'TEnumHelp.Cast (Value: Integer)'. В чем преимущества этого? –

Смежные вопросы