问题
I would like to use TObjectDataset which relies on TObjectList<> (System.Generics.Collections / Spring.Collections) but only have a TObjectList (System.Contnrs). Is there any way besides for iterating through objects and building a new TObjectList<> to get this working? Ultimately I would like to couple the TObjectList to an Objectdataset in order to bind to an UI.
回答1:
Your question is slightly wrong. The Spring4d TObjectDataSet takes an IObjectList
interface which is a specialization of IList<T>
where T
is TObject
.
This contract is matched by the Contnrs.TObjectList
. So "simply" create a wrapper class for your TObjectList
that implements IObjectList
. I put simply in quotes because this interface has quite a lot of methods. You can use TListBase<T>
as base class for your adapter which already has all methods implemented. Then you only need to override a few (take a look at TList<T>
which ones those are).
One important detail to know is that the TObjectDataSet
needs to know the exact class of the objects in your list. This is done via the ElementType
property of the IObjectList
. If that returns TObject
though this is not very helpful. So you need to override that method.
Edit: Here is the full code of such an adapter class:
unit Spring.Collections.ObjectListAdapter;
interface
uses
Contnrs,
TypInfo,
Spring.Collections,
Spring.Collections.Base;
type
TObjectListAdapter = class(TListBase<TObject>, IObjectList)
private
fList: TObjectList;
fClassType: TClass;
protected
function GetCapacity: Integer; override;
function GetCount: Integer; override;
function GetElementType: PTypeInfo; override;
function GetItem(index: Integer): TObject; override;
procedure SetCapacity(value: Integer); override;
procedure SetItem(index: Integer; const value: TObject); override;
public
constructor Create(const list: TObjectList; classType: TClass);
procedure Delete(index: Integer); override;
function Extract(const item: TObject): TObject; override;
procedure Insert(index: Integer; const item: TObject); override;
procedure Exchange(index1, index2: Integer); override;
procedure Move(currentIndex, newIndex: Integer); override;
end;
implementation
uses
Classes,
Types;
{ TObjectListAdapter }
constructor TObjectListAdapter.Create(const list: TObjectList; classType: TClass);
begin
inherited Create;
fList := list;
fClassType := classType;
end;
procedure TObjectListAdapter.Delete(index: Integer);
begin
fList.Delete(index);
end;
procedure TObjectListAdapter.Exchange(index1, index2: Integer);
begin
fList.Exchange(index1, index2);
end;
function TObjectListAdapter.Extract(const item: TObject): TObject;
begin
Result := fList.Extract(item);
end;
function TObjectListAdapter.GetCapacity: Integer;
begin
Result := fList.Capacity;
end;
function TObjectListAdapter.GetCount: Integer;
begin
Result := fList.Count;
end;
function TObjectListAdapter.GetElementType: PTypeInfo;
begin
Result := fClassType.ClassInfo;
end;
function TObjectListAdapter.GetItem(index: Integer): TObject;
begin
Result := fList[index];
end;
procedure TObjectListAdapter.Insert(index: Integer; const item: TObject);
begin
fList.Insert(index, item);
end;
procedure TObjectListAdapter.Move(currentIndex, newIndex: Integer);
begin
fList.Move(currentIndex, newIndex);
end;
procedure TObjectListAdapter.SetCapacity(value: Integer);
begin
fList.Capacity := value;
end;
procedure TObjectListAdapter.SetItem(index: Integer; const value: TObject);
begin
fList[index] := value;
end;
end.
回答2:
Is there any way besides for iterating through objects and building a new
TObjectList<T>
to get this working?
There is not. The two types are not compatible.
来源:https://stackoverflow.com/questions/43024863/process-to-convert-tobjectlist-to-tobjectlistt-to-use-in-tobjectdataset