2014-07-25 28 views
1

我使用memtables使用LiveBinding将枚举类型与组合框关联。如何从令人沮丧的情况填充memtables?

但是我有很多他们与他们的方式我做的是太糟糕(复制/粘贴)

例如,我有以下枚举:

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

和我创建一个函数来给字符串相当于:

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; 

在一个数据模块,我把我的memTable,我需要用下面的鳕鱼来填充它,我用的是表的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; 

所有的工作,但我需要为每个新的脓肿做,我有几十个。最终,我将需要将我当前的memtable更改为其他,这是自动执行此过程的另一个关注点。当前的memtable有时不适用于Android。我正在寻找一种方法来自动化这个过程,或使用泛型,或任何,在DataModule我只需要像这样的东西:PopulateEnum(Table,Enum);

最好的解决办法是建立从这个memTable中继承的组成部分,在某种程度上定义什么是需要枚举所有的魔法发生(包括enumtostr的选择)

+0

你只想用整数和字符串填充表格吗?为什么不使用'TDictionary '来填充表并遍历该键并获取该键的字符串? –

+0

如果你想迭代(几乎)任何枚举看这个http:// stackoverflow。com/questions/12379032/using-an-enum-with-generics –

回答

2

这里是枚举的通用包装器,获取表示枚举的序号值和名称的integer,string对的数组。

一个小测试

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

我会说你有两个更容易的选择这里

你可以用GetEnumName(TypeInfo(TEnumResourceType), ord(enum))替代EnumResourceTypeToStr(enum)或者其中的一些变化。这有一个缺点,就是它只是返回出现在程序中的枚举。

或者添加一个常量EnumNames: array [TEnumResourceType] of string = ('....等填充您的字符串列表。这些可以作为EnumNames[enum]访问。这允许你使用任意字符串,编译器会提醒你添加额外的条目,如果你扩展枚举。

+0

+1,你的第二个选择很容易维护,并附带编译时检查。 –

+0

+1实际上我想将两个答案定义为接受。你持有这些字符串的选择是非常有用的,我将把这个添加到另一个解决方案中,两者都将很好地解决我的问题。谢谢你。 –