Salut.
Ich möchte mir ein Objekt zum Verwalten von Records, deren Quelle ein Stream ist, schaffen.
Im ersten Schritt habe ich mir die Klasse TList genommen und an sie die Information über die Recordgröße geknüpft. Fertig war meine Klasse TRecordList.
Im zweiten Schritt möchte ich erreichen, dass diese Liste ein TStream-Objekt als Standarddatenquelle nutzt. Mit der Eigenschaft Items[Index] soll dann auf jeden Record zugegriffen werden können. Ist der Record noch nicht im Speicher soll er aus dem Stream gelesen und in den Speicher kopiert werden. In jedem Fall gibt Items dann einen Pointer auf den Record im Speicher zurück. (Das vertraute Verhalten von TList.)
Dabei stellt sich mir folgendes Problem: Wie kann ich sicherstellen, dass die Records im Speicher gleich denen im Stream sind? Denn die Anwendung führt an anderer Stelle möglicherweise Schreib-Lese-Operationen an dem Stream durch.
Ich habe mir überlegt, wenn es dasselbe Objekt handhaben würde, bekäme es die Schreib-Lese-Operationen mit, und könnte geschriebene Records aus dem Speicher entfernen. (Besteht noch Lesebedarf werden sie ja erneut in den Speicher geholt.)
Folglich brauche ich also ein Objekt, das TStream und TList zugleich ist. Das aber geht in Delphi nicht. Was kann ich tun? Hat jemand eine kozetionell andere Lösung? Ich bin für alles offen.
Noch ein Hinweis: Interfaces kommen nicht in Frage. Im Gesamtkontext gibt es zuviele Delphi-Routinen, die ich benutzen möchte, die TList- und TStream-Objekte erwarten.
Panthrax.
Hier noch etwas Quelltext zum Verständnis:
Delphi-Quellcode:
type
{ TRecordList
Hier wird nur die Möglichkeit geschaffen, die Information über die Recordgröße bei der Liste zu hinterlegen. }
TRecordList = class(TList)
private
FRecordSize: Integer;
published
property RecordSize: Integer read FRecordSize write FRecordSize;
constructor Create(RecordSize: Integer);
end;
constructor TRecordList.Create(RecordSize: Integer);
begin
FRecordSize:=RecordSize;
end;
type
{ TRecordListStreamStreamBounded
Diese Klasse ist nur eine Beispielimplementierung um zu demonstrieren, was die Eigenschaft Items tun soll, wenn ein Record nachgrfragt wird. }
TRecordListStreamStreamBounded = class(TRecordList)
private
FBoundedStream: TStream;
function GetItems(Index: Integer):Pointer;
procedure SetItems(Index: Integer; const Value: Pointer);
public
property Items[Index: Integer]:Pointer read GetItems write SetItems; default;
published
constructor Create(BoundedStream: TStream);
{ Methoden die Records aus dem Speicher zu entfernen und zu speichern gibt es natürlich auch noch... }
end;
constructor TRecordListStreamStreamBounded.Create(BoundedStream: TStream);
begin
FBoundedStream:=BoundedStream;
end;
function TRecordListStreamStreamBounded.GetItems(Index: Integer): Pointer;
var
RecordPtr: Pointer;
begin
Result:=inherited Items[Index];
if Result = NIL then with BoundedStream do
begin
GetMem(RecordPtr,RecordSize);
try
Seek(soFromBeginning,Index*RecordSize);
Read(RecordPtr^,RecordSize);
// Auf Read(...) <> RecordSize zu prüfen spar' ich mir jetzt mal.
except
FreeMem(RecordPtr,RecordSize);
end;
end;
end;
procedure TRecordListStreamStreamBounded.SetItems(Index: Integer;
const Value: Pointer);
begin
inherited Items[Index]:=Value;
end;