Содержание материала

 

Answer 2:

The solution above will work, but it forces you to implement streaming support for each of the TStreamableObject objects. Delphi has already implemented this mechanism in for the TPersistent class and the TComponent class, and you can use this mechanism. The class I include here does the job. It holds classes that inherit from TUmbCollectionItem (which in turn inherits from Delphi TCollectionItem), and handles all the streaming of the items. As the items are written with the Delphi mechanism, all published data is streamed.

Notes: This class does not support working within the delphi IDE like TCollection. All objects inheriting from TUmbCollectionItem must be registered using the Classes.RegisterClass function. All objects inheriting from TUmbCollectionItem must implement the assign function. By default, the TUmbCollection owns its items (frees them when the collection is freed), but this functionality can be changed.

 

Code:

unit UmbCollection;

 

interface

 

uses

Windows, Messages, SysUtils, Classes, contnrs;

 

 

type

TUmbCollectionItemClass = Classof TUmbCollectionItem;

TUmbCollectionItem = class(TCollectionItem)

private

   FPosition: Integer;

public

   {when overriding this method, you must call the inherited assign.}

   procedure Assign(Source: TPersistent); Override;

published

   {the position property is used by the streaming mechanism to place the object in the

   right position when reading the items. do not use this property.}

   property Position: Integer read FPosition write FPosition;

end;

 

TUmbCollection = class(TObjectList)

private

   procedure SetItems(Index: Integer; Value: TUmbCollectionItem);

   function GetItems(Index: Integer): TUmbCollectionItem;

public

   function Add(AObject: TUmbCollectionItem): Integer;

   function Remove(AObject: TUmbCollectionItem): Integer;

   function IndexOf(AObject: TUmbCollectionItem): Integer;

   function FindInstanceOf(AClass: TUmbCollectionItemClass; AExact: Boolean = True;

                                                 AStartAt: Integer = 0): Integer;

   procedure Insert(Index: Integer; AObject: TUmbCollectionItem);

 

   procedure WriteToStream(AStream: TStream); virtual;

   procedure ReadFromStream(AStream: TStream); virtual;

 

   property Items[Index: Integer]: TUmbCollectionItem read GetItems write SetItems; default;

published

   property OwnsObjects;

end;

 

implementation

 

{ TUmbCollection }

 

function ItemsCompare(Item1, Item2: Pointer): Integer;

begin

Result := TUmbCollectionItem(Item1).Position - TUmbCollectionItem(Item2).Position;

end;

 

 

function TUmbCollection.Add(AObject: TUmbCollectionItem): Integer;

begin

Result := inherited Add(AObject);

end;

 

 

function TUmbCollection.FindInstanceOf(AClass: TUmbCollectionItemClass;

AExact: Boolean; AStartAt: Integer): Integer;

begin

Result := inherited FindInstanceOf(AClass, AExact, AStartAt);

end;

 

 

function TUmbCollection.GetItems(Index: Integer): TUmbCollectionItem;

begin

Result := inherited Items[Index] as TUmbCollectionItem;

end;

 

 

function TUmbCollection.IndexOf(AObject: TUmbCollectionItem): Integer;

begin

Result := inherited IndexOf(AObject);

end;

 

 

procedure TUmbCollection.Insert(Index: Integer; AObject: TUmbCollectionItem);

begin

inherited Insert(Index, AObject);

end;

 

 

procedure TUmbCollection.ReadFromStream(AStream: TStream);

var

Reader: TReader;

Collection: TCollection;

ItemClassName: string;

ItemClass: TUmbCollectionItemClass;

Item: TUmbCollectionItem;

i: Integer;

begin

Clear;

Reader := TReader.Create(AStream, 1024);

try

   Reader.ReadListBegin;

   whilenot Reader.EndOfList do

   begin

     ItemClassName := Reader.ReadString;

     ItemClass := TUmbCollectionItemClass(FindClass(ItemClassName));

     Collection := TCollection.Create(ItemClass);

     try

       Reader.ReadValue;

       Reader.ReadCollection(Collection);

       for i := 0to Collection.Count - 1do

       begin

         item := ItemClass.Create(nil);

         item.Assign(Collection.Items[i]);

         Add(Item);

       end;

     finally

       Collection.Free;

     end;

   end;

   Sort(ItemsCompare);

   Reader.ReadListEnd;

finally

   Reader.Free;

end;

end;

 

 

function TUmbCollection.Remove(AObject: TUmbCollectionItem): Integer;

begin

Result := inherited Remove(AObject);

end;

 

 

procedure TUmbCollection.SetItems(Index: Integer; Value: TUmbCollectionItem);

begin

inherited Items[Index] := Value;

end;

 

 

procedure TUmbCollection.WriteToStream(AStream: TStream);

var

Writer: TWriter;

CollectionList: TObjectList;

Collection: TCollection;

ItemClass: TUmbCollectionItemClass;

ObjectWritten: arrayof Boolean;

i, j: Integer;

begin

Writer := TWriter.Create(AStream, 1024);

CollectionList := TObjectList.Create(True);

try

   Writer.WriteListBegin;

   {init the flag array and the position property of the TCollectionItem objects.}

   SetLength(ObjectWritten, Count);

   for i := 0to Count - 1do

   begin

     ObjectWritten[i] := False;

     Items[i].Position := i;

   end;

   {write the TCollectionItem objects. we write first the name of the objects class,

   then write all the object of the same class.}

   for i := 0to Count - 1do

   begin

     if ObjectWritten[i] then

       Continue;

     ItemClass := TUmbCollectionItemClass(Items[i].ClassType);

     Collection := TCollection.Create(ItemClass);

     CollectionList.Add(Collection);

     {write the items class name}

     Writer.WriteString(Items[i].ClassName);

     {insert the items to the collection}

     for j := i to Count - 1do

       if ItemClass = Items[j].ClassType then

       begin

         ObjectWritten[j] := True;

         (Collection.Add as ItemClass).Assign(Items[j]);

       end;

     {write the collection}

     Writer.WriteCollection(Collection);

   end;

finally

   CollectionList.Free;

   Writer.WriteListEnd;

   Writer.Free;

end;

end;

 

 

{ TUmbCollectionItem }

 

procedure TUmbCollectionItem.Assign(Source: TPersistent);

begin

if Source is TUmbCollectionItem then

   Position := (Source as TUmbCollectionItem).Position

else

   inherited;

end;

 

end.

 

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить