我使用内存表通过LiveBinding将枚举类型与组合框连接起来。
但是我有很多,他们做的方式太糟糕了(复制/粘贴)
例如,我有以下列举:
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;
在一个数据模块中,我放置了内存表,需要填充它,我在表的AFTEROPEN事件中使用以下代码:
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;
所有这些都有效,但是对于每次新的灌肠,我都需要这样做,我有数十个。最终,我需要将当前的内存表更改为其他内存表,这是使流程自动化的又一个关注点。当前的内存表有时无法在Android上运行。
我正在寻找一种自动化此过程的方法,或者使用泛型或其他方法,在DataModule中,我只需要这样的东西:PopulateEnum(Table,Enum);
最好的解决方案是创建一个从此memtable继承的组件,并以某种方式定义所需的枚举以及发生的所有魔术(包括枚举的选择)
最佳答案
这是枚举的通用包装,以获取表示顺序值和枚举名称的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
and here is the unit that will do the work
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;