2013-03-04 8 views
9

Ich hoffe, so etwas wie ein „TOwnedStringList“ (Name ist eine Fiktion Klasse) zu erstellen, die ich als konstruieren könnte:Wie erstellt man einen TStringList-Nachkomme mit Owner, der die TStringList automatisch freigibt?

sl := TOwnedStringList.Create(Self); 
sl.Sorted := True; 
sl.Duplicates := dupIgnore; 
sl.Add(...); 
// etc... 

Wo Self ein Formular (zum Beispiel) sein könnte, so dass der Eigentümer Auto frei die StringList. Ich möchte vermeiden, sl.Free selbst zu nennen.

Ist das möglich?

Antwort

13

Das wird ein bisschen unordentlich. Du musst so etwas machen.

type 
    TOwnerComponent = class(TComponent) 
    private 
    FOwnedObject: TObject; 
    public 
    constructor Create(Owner: TComponent; OwnedObject: TObject); 
    destructor Destroy; override; 
    end; 

    TOwnedStringList = class(TStringList) 
    private 
    FOwner: TOwnerComponent; 
    public 
    constructor Create(Owner: TComponent); 
    destructor Destroy; override; 
    end; 

{ TOwnerComponent } 

constructor TOwnerComponent.Create(Owner: TComponent; OwnedObject: TObject); 
begin 
    inherited Create(Owner); 
    FOwnedObject := OwnedObject; 
end; 

destructor TOwnerComponent.Destroy; 
begin 
    FOwnedObject.Free; 
    inherited; 
end; 

{ TOwnedStringList } 

constructor TOwnedStringList.Create(Owner: TComponent); 
begin 
    inherited Create; 
    if Assigned(Owner) then 
    FOwner := TOwnerComponent.Create(Owner, Self); 
end; 

destructor TOwnedStringList.Destroy; 
begin 
    if Assigned(FOwner) and not (csDestroying in FOwner.ComponentState) then 
    begin 
    FOwner.FOwnedObject := nil; 
    FOwner.Free; 
    end; 
    inherited; 
end; 

Grundsätzlich erstellen Sie eine Instanz von TOwnerComponent, die von der Owner, die Sie TOwnedStringList.Create passieren gehört. Wenn das Owner stirbt, zerstört es die TOwnerComponent, die wiederum Ihre String-Liste zerstört.

Der Code ist resilient zu einem expliziten Free, der in der String-Liste aufgerufen wird.

+0

+1 Gleicher Trick wie mit Schnittstellen in Aufzeichnungen – jpfollenius

+1

Sieht vielversprechend aus. Soll der TOwnerComponent-Konstruktor mit der 'Wiedereinführung'-Direktive erstellt werden? Wie kann ich die 'TOwnedStringList' gegen' sl.Create (nil) 'und explizite' sl.Free' schützen? – ZigiZ

+1

'Create (nil)' ist in Ordnung. Das bedeutet nur, kein Besitzer, lass mich die Verantwortung übernehmen. Oder wenn Sie das nicht wollen, dann lösen Sie eine Ausnahme aus. Explizite 'Free' wird ein wenig mehr nachdenken. Trage mit mir. –