我使用内存表通过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继承的组件,并以某种方式定义所需的枚举以及发生的所有魔术(包括枚举的选择)

最佳答案

这是枚举的通用包装,以获取表示顺序值和枚举名称的integerstring对数组。

一点测试

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;

08-20 00:38