如何在集合中存储记录或类类型并转换为TObject

时间:2018-09-11 10:19:14

标签: delphi

我正在编写一个从TComboBox继承的组件。该组件具有通用方法,用于从私有字典中添加和检索值(可以是记录或类类型),并以键作为值的字符串表示形式的项目索引。

  TGenericCombo = class (TComboBox)
  private
    FValues: TDictionary<integer, TValue>;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure AddValue<T>(const StringValue: string; Value: T); overload;
    procedure AddValue<T>(Pair: TPair<T, string>); overload;

    procedure AddValues<T>(StringFunction: TCalculateStringFunction<T>; Values: TList<T>); overload;
    procedure AddValues<T>(Dictionary: TDictionary<T, string>); overload;

    function GetCurrentValue<T>: T;
    procedure SetCurrentValue<T>(Value: T);
  end;

这是AddItem方法,当前将值存储为TValue,我也尝试过Variant。

procedure TGenericCombo.AddValue<T>(const StringValue: string; Value: T);
begin
  Items.Add(StringValue);
  FValues.Add(Items.Count - 1, TValue.From(Value));
end;

我遇到的问题是,当要在组合中设置所选值时,我正在将字典中的值强制转换为TObject以便与过去的值进行比较。这引发了“无效类型强制转换”运行时异常。 TRttiHelper.ObjectsAreEqual接受2个TObject作为参数。

procedure TGenericCombo.SetCurrentValue<T>(Value: T);
var
  i: integer;
  FFound: Boolean;
  ListValue: TPair<integer, TValue>;
begin
  for ListValue in FValues do
    if TRttiHelper.ObjectsAreEqual(TValue.From(ListValue.Value).AsObject, TValue.From(Value).AsObject) then
    begin
      ItemIndex := ListValue.Key;
      FFound := True;
      Break
    end;

  if not FFound then
    ItemIndex := -1;
end;

我确定应该将值存储为哪种类型,这些值又可以是记录类型或类,以使其正常工作。

编辑: 我认为添加几个用法示例会很有用。

TTestEnum =(teEnum1,teEnum2,teEnum3);

  TTestObject = class
  private
    FStringProperty: string;
  public
    constructor Create(const StringProperty: string);

    property StringProperty: string read FStringProperty write FStringProperty;
  end;

  TForm3 = class(TForm)
    GenericCombo1: TGenericCombo;
    GenericCombo2: TGenericCombo;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var
  TestList: TObjectList<TTestObject>;
begin
  TestList := TObjectList<TTestObject>.Create;
  try
     TestList.Add(TTestObject.Create('Object 1'));
     TestList.Add(TTestObject.Create('Object 2'));
     TestList.Add(TTestObject.Create('Object 3'));

     GenericCombo1.AddValues<TTestList>(function(x: TTestObject): string begin Result := x.StringProperty end, TestObject);
  finally
    TestList.Free;
  end;

end;

{ TTestObject }

constructor TTestObject.Create(const StringProperty: string);
begin
  FStringProperty := StringProperty;
end;

procedure TForm3.Button2Click(Sender: TObject);
var
  TestList: TDictionary<TTestEnum, string>;
begin
  TestList := TDictionary<TTestEnum, string>.Create;
  try
     TestList.Add(teEnum1, 'Enum 1');
     TestList.Add(teEnum2, 'Enum 2');
     TestList.Add(teEnum3, 'Enum 3');

     GenericCombo1.AddValues<TTestEnum>(TestList);
  finally
    TestList.Free;
  end;
end;

0 个答案:

没有答案