2014-07-25 7 views
1

필자는 memtables를 사용하여 열거 형을 combobox로 와이어 링합니다 (LiveBinding을 사용). 그러나enumarations에서 memtables를 채우는 방법?

나는 그들을 많이 가지고 그들은 방법 내가 너무 나쁜 (복사/붙여 넣기)를하고있는 중이 예를 들어

, 나는 다음과 같은 열거 있습니다

TEnumResourceType  = (trtApp, trtTab, trtSection, trtField, trtCommand, trtOther); 

하고 I를 위해를 문자열에 상응 제공하는 함수를 만들어 : 내 memtable을 놓습니다 데이터 모듈에서

function EnumResourceTypeToStr(AEnum: TNaharEnumResourceType): string; 
begin 
    case AEnum of 
    trtApp  : result := 'Aplicação'; 
    trtTab  : result := 'Pagina (Tab)'; 
    trtSection : result := 'Secção'; 
    trtField : result := 'Campo'; 
    trtCommand : result := 'Comando'; 
    trtOther : result := 'Outro'; 
    end; 
end; 

을하고 난 다음 대구로, 나는 테이블의 AFTEROPEN 이벤트를 사용하고 그것을 채울 필요 e :

procedure TDMGlobalSystem.vtResourceTypeAfterOpen(DataSet: TDataSet); 
var 
    enum : TEnumResourceType; 
begin 
    inherited; 

    for enum := Low(TEnumResourceType) to High(TEnumResourceType) do 
    DataSet.InsertRecord([EnumResourceTypeToStr(enum), Ord(enum)]); 
end; 

모두 작동하지만 모든 새 enumaration에 대해이 작업을 수행해야하며 수십 개가 필요합니다. 결국 현재의 memtable을 다른 것으로 변경해야하며 이는 프로세스를 자동화하는 추가 관심사입니다. 현재 memtable이 Android에서 작동하지 않는 경우가 있습니다.

나는이 프로세스를 자동화하거나 generics를 사용하는 방법을 찾고 있는데, DataModule에서는 다음과 같은 것이 필요하다. PopulateEnum (Table, Enum);

가장 좋은 방법은이 memtable로부터 상속 된 구성 요소를 생성하고 어떻게 든 열거 필요한 사항을 정의하고 모든 마법합니다 (enumtostr의 선택 포함)이 발생 될 수

난 당신이 개 쉽게 선택이 말한 것
+0

정수 및 문자열로만 표를 채우시겠습니까? 왜 'TDictionary '을 사용하고 테이블을 채우지 않고 키를 반복하고 그 키의 문자열을 얻는가? –

+0

(거의) 열거 형을 반복하면서이 http : // stackoverflow를 반복하고 싶다면.com/questions/12379032/enum-with-generics –

답변

2

다음은 열거 형에 대한 서수 값과 이름을 나타내는 integer, string 쌍의 배열을 가져 오는 enum의 일반 래퍼입니다.

약간의 테스트

program so_24955704; 

{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils, 
    EnumValueStore in 'EnumValueStore.pas'; 

type 
    TEnumResourceType = (trtApp, trtTab, trtSection, trtField, trtCommand, trtOther); 

procedure PrintEnumValueStore(AEnumValueStore : TEnumValueStore); 
var 
    LEnumValuePair : TEnumValuePair; 
begin 
    for LEnumValuePair in AEnumValueStore.GetKeyValues do 
    begin 
     Writeln(LEnumValuePair.Key, '-', LEnumValuePair.Value); 
    end; 
end; 

procedure TestEnum; 
var 
    LEnumValueStore : TEnumValueStore<TEnumResourceType>; 
begin 
    LEnumValueStore := TEnumValueStore<TEnumResourceType>.Create; 
    try 
    // print default names 
    PrintEnumValueStore(LEnumValueStore); 

    WriteLn; 

    // set the custom names 
    LEnumValueStore.SetValue(trtApp, 'Aplicação'); 
    LEnumValueStore.SetValue(trtTab, 'Pagina (Tab)'); 
    LEnumValueStore.SetValue(trtSection, 'Secção'); 
    LEnumValueStore.SetValue(trtField, 'Campo'); 
    LEnumValueStore.SetValue(trtCommand, 'Comando'); 
    LEnumValueStore.SetValue(trtOther, 'Outro'); 

    // print the default values 
    PrintEnumValueStore(LEnumValueStore); 
    finally 
    LEnumValueStore.Free; 
    end; 
end; 

begin 
    try 
    TestEnum; 
    except 
    on E : Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    ReadLn; 

end. 

다음과 같은 출력을

 
0-App 
1-Tab 
2-Section 
3-Field 
4-Command 
5-Other 

0-Aplicação 
1-Pagina (Tab) 
2-Secção 
3-Campo 
4-Comando 
5-Outro 

을 생산하고 여기에 작업

unit EnumValueStore; 

interface 

uses 
    System.Generics.Collections; 

type 
    TEnumValuePair = TPair<Integer, string>; 

    TEnumValueStore = class abstract 
    public 
    function GetKeyValues : TArray<TEnumValuePair>; virtual; abstract; 
    end; 

    TEnumValueStore<TEnumKey> = class(TEnumValueStore) 
    private 
    FValueDict : TDictionary<TEnumKey, string>; 
    public 
    constructor Create; 
    destructor Destroy; override; 
    procedure SetValue(AKey : TEnumKey; const AValue : string); 
    function GetKeyValues : TArray<TEnumValuePair>; override; 
    end; 

implementation 

uses 
    SimpleGenericEnum; 

{ TEnumValueStore<TEnumKey> } 

constructor TEnumValueStore<TEnumKey>.Create; 
begin 
    inherited Create; 
    FValueDict := TDictionary<TEnumKey, string>.Create; 
end; 

destructor TEnumValueStore<TEnumKey>.Destroy; 
begin 
    FValueDict.Free; 
    inherited; 
end; 

function TEnumValueStore<TEnumKey>.GetKeyValues : TArray<TEnumValuePair>; 
var 
    LEnum : TEnum<TEnumKey>; 
    LMin, LMax : Integer; 
    LCount : Integer; 
    LIdx : Integer; 
    LStr : string; 
begin 
    LMin := LEnum.Ord(LEnum.Low); 
    LMax := LEnum.Ord(LEnum.High); 
    LCount := LMax - LMin + 1; 
    SetLength(Result, LCount); 

    LCount := 0; 
    for LIdx := LMin to LMax do 
    begin 
     LEnum := LIdx; 
     if FValueDict.ContainsKey(LEnum) 
     then 
     LStr := FValueDict[LEnum] 
     else 
     LStr := LEnum; 
     Result[LCount] := TEnumValuePair.Create(LEnum, LStr); 
     Inc(LCount); 
    end; 
end; 

procedure TEnumValueStore<TEnumKey>.SetValue(AKey : TEnumKey; const AValue : string); 
begin 
    FValueDict.AddOrSetValue(AKey, AValue); 
end; 

end. 
내가 단위 SimpleGenericEnum를 사용

만 할 것입니다 단위는있다 내부에있는 작은 버그입니다.

class function TEnum<T>.High: T; 
begin 
    // original code 
    // Result := Cast(_TypeData.MaxValue); 
    Result := Cast(GetTypeData.MaxValue); 
end; 

class function TEnum<T>.Low: T; 
begin 
    // original code 
    // Result := Cast(_TypeData.MinValue); 
    Result := Cast(GetTypeData.MinValue); 
end; 
+0

정확히 내가 필요한 것. 열거 형을 나타 내기위한 표준 데이터 세트를 채우는 메소드를 추가하고 완료되었습니다. 감사! –

2

여기

EnumResourceTypeToStr(enum)GetEnumName(TypeInfo(TEnumResourceType), ord(enum)) 또는 그 변형으로 대체 할 수 있습니다. 이것은 프로그램에 나타나는 열거 형을 단순히 반환한다는 단점이 있습니다.

또는 문자열의 목록으로 채워진 상수 EnumNames: array [TEnumResourceType] of string = ('.... 등을 추가하십시오. 그런 다음 EnumNames[enum]으로 액세스 할 수 있습니다. 이렇게하면 임의의 문자열을 사용할 수 있으며 열거 형을 확장하면 컴파일러에서 항목을 추가하도록 알려줍니다.

+0

+1, 두 번째 대안은 유지하기 쉽고 컴파일 시간 검사가 제공됩니다. –

+0

+1 실제로 두 답변을 모두 받아들이고 싶다고 정의하고 싶었습니다. 문자열을 잡아 둘 수있는 대안은 매우 유용합니다. 다른 솔루션에도이를 추가 할 것이고 두 가지 모두 내 문제를 아주 잘 해결할 것입니다. 고마워요. –