Search code examples
delphidatasetspring4d

Process to convert TObjectlist to TObjectList<T> to use in TObjectDataset


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.


Solution

  • 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.