如何从枚举中填充内存表? [英] How to populate memtables from enumarations?

查看:59
本文介绍了如何从枚举中填充内存表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用memtables通过LiveBinding将枚举类型与组合框连接起来。

I use memtables to wire enumerated type with comboboxes using LiveBinding.

但是我有很多它们,它们的作用方式太糟糕了(复制/粘贴)

However I have a lot of them and they way I am doing is way too bad (copy/paste)

例如,我有以下枚举:

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

为此,我创建了一个函数来提供等效的字符串:

and for that I created a function to give the string equivalent:

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事件带有以下代码的表:

In a datamodule I place my memtable and I need to populate it, I am using the AFTEROPEN event of the table with the following code:

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上运行。

All that works, however I need to do that for each new enumaration and I have dozens. Eventually I will need to change my current memtable to other and that is an added concern to automate the process. The current memtable sometimes does not work on Android.

我正在寻找一种自动化此过程的方法,或者使用泛型或其他任何方式,只需在DataModule中使用即可像这样的东西:PopulateEnum(Table,Enum);

I am looking in a way to automate this process, or using generics, or whatever, that in the DataModule I only need something like: PopulateEnum(Table, Enum);

最好的解决方案是创建一个从此内存表继承的组件,并以某种方式定义所需的枚举和所有发生的魔术(包括选择枚举)

The best solution would be creating a component inherited from this memtable and somehow define what is the enum required and all the magic happens (including the selection of the enumtostr)

推荐答案

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

Here is a generic wrapper for enums to get an array of integer,string pair representing the ordinal value and the name for the enums.

稍作测试

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 ,但您需要纠正其中的一个小错误

I use the unit SimpleGenericEnum but there is a small bug inside you need to correct

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;

这篇关于如何从枚举中填充内存表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆