Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Tutorials und Kurse (https://www.delphipraxis.net/36-tutorials-und-kurse/)
-   -   Delphi for...in...do für COM Collections (https://www.delphipraxis.net/36421-do-fuer-com-collections.html)

sakura 19. Dez 2004 19:10


for...in...do für COM Collections
 
Delphi 2005 gibt uns endlich das for...in...do Konstrukt, um über Listen auf einfache Art und Weise zu iterieren. Leider unterstützt es aber keine COM Kollektionen vo Typ IEnumVariant. Mit diesem Tutorial möchte ich Euch eine kleine Einleitung in dieses Thema geben und wie man dieses Konstrukt in eigenen Objekten unterstützen kann.

Hinweis
Dieses Tutorial gilt nur für die Delphi Win32 Personalität, nicht für die Delphi.NET Personalität von Delphi 2005.


Eine kurze Einführung in das Thema for...in...do hat Danny Thorpe in seinem Blog gegeben. Der Eintrag "New For Loop Syntax" ist bereits seit einigen Monaten bekannt. Wer das Konstrukt noch nicht kennt möge sich in Danny's Blog oder seiner Hilfe informieren. ;)

sakura 19. Dez 2004 19:20

Re: for...in...do für COM Collections
 
COM Enumerationen werden nicht unterstützt, was nun?


Leider unterstützt Delphi 2005 die neue for Syntax nicht für die COM Kollektionen. Diese sind jedoch die, welche sich in Delphi mit am schwersten ansprechen lassen. Deshalb wäre es schon sehr angenehm das neue Konstrukt auch für diese nuzten zu können. Die in diesem Tutorial aufgezeigte Lösung bietet sich für über 95% aller COM Kollektionen an, da diese auf dem IEnumVariant Interface basieren, für andere Varianten kann dieser Code entsprechend angepasst werden.

sakura 19. Dez 2004 19:31

Re: for...in...do für COM Collections
 
Wie funktioniert diese for...in Schleife in Delphi


Bevor ich den Code für COM Kollektionen erkläre werde ich zuerst aufklären, wie Delphi die for...in...do Syntax für Objekte unterstützt.

Als Beispiel nehme ich eine Stringliste, fühle diese mit ein paar Werten und lese diese dann einzeln in einer for...in...do Schleife aus.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  S: String;
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  try
    Strings.Add('1');
    Strings.Add('2');
    Strings.Add('3');
    for S in Strings do
      ShowMessage(S);
  finally
    Strings.Free;
  end;
end;
Der eigentlich interessante Teil ist folgender:
Delphi-Quellcode:
    for S in Strings do
      ShowMessage(S);
Wenn Delphi den Code kompiliert, dann werden diese zwei Zeilen ähnlich dem folgenden Code-Abschnitt umgesetzt:
Delphi-Quellcode:
    StringEnum := Strings.GetEnumerator;
    try
      while StringEnum.MoveNext do
      begin
        S := StringEnum.Current;
        ShowMessage(S);
      end;
    finally
      StringEnum.Free;
    end;
Als erstes holt Delphi sich ein Enumerator-Objekt heran, welches genutzt wird, um die Liste aller Strings zu durchlaufen. Solange das Enumerator-Objekt weitere Strings liefern kann, wird der jeweils aktuelle String der Variablen "S" zugewiesen und somit verfügbar gemacht.
Hinweis
Auf "S" kann innerhalb der for...in...do Schleife nur lesend zugegriffen werden. Gleiches gilt nicht, wenn man stattdessen obigen Code einsetzt.


Damit es nicht zu Speicherlöchern kommt, wird der Code von Delphi automatisch in einen try...finally...end Block gesetzt. So wird das Enumerator-Objekt auch denn wieder freigegeben, wenn es innerhalb der Schleife zu einer Ausnahme (Exception) kommt. Delphi gibt den Enumerator immer wieder explizit frei. Daher kann ein Enumerator auch nur für eine Schleife genutzt werden und muss für jede Schleife erneut bereitgestellt werden.

sakura 19. Dez 2004 19:37

Re: for...in...do für COM Collections
 
Einen Enumerator für COM Kollektionen anbieten


Als ich den Code für COM Kollektionen erstellt habe, habe ich mich gleichzeitig auf den Fakt gestützt, dass Delphi durch den try...finally...end Block sicherstellt, dass das Objekt auch wieder freigegeben wird.

Da man aber ein fertiges COM Objekt nicht einfach um die nötigen Methoden erweitern kann, habe ich einen kleinen Umweg eingelegt. Eine Hilfsfunktion namens GetCOMEnumerator() erstellt ein Objekt, welches die von Delphi verlangte Methode GetEnumerator() integriert. Dieses Objekt wird an die for...in...do Schleife übergeben. Die Methode GetEnumerator() liefert einfach das Objekt zurück, welches diese implementiert. Somit wird das am Ende auch wieder freigegeben und der Speicher wieder aufgeräumt.

Die interessanteste Methode des Objektes ist MoveNext:
Delphi-Quellcode:
function TComEnumerator.MoveNext: Boolean;
var
  OleCurrent: OleVariant;
  Fetched: Cardinal;
begin
  if FEnum <> nil then
  begin
    // fetch the next element from the collection list
    FEnum.Next(1, OleCurrent, Fetched);
    if Fetched = 1 then
    begin
      // another object was fetched
      FCurrent := OleCurrent;
      Result := True;
    end
    else
    begin
      // no more objects in enumaration
      Result := False;
    end;
  end
  else
  begin
    Result := False;
  end;
end;
Um den Enumerator jetzt einzubinden, muss man ihn wie folgend einbinden:
Delphi-Quellcode:
  // iterate all drives
  for Drive in GetCOMEnumerator(Drives._NewEnum) do
    // write the drive letter to the console
    WriteLn((Drive as IDrive).DriveLetter);

sakura 19. Dez 2004 19:38

Re: for...in...do für COM Collections
 
Der Quellcode für den COM Enumerator könnt Ihr in der Borland CodeCentral unter dem Eintrag 22263 finden und runterladen.

Viel Spaß damit!

...:cat:...

Lemmy1 29. Okt 2005 13:12

Re: for...in...do für COM Collections
 
Komme nicht auf Quality Central (ist wohl down). Könntest Du den Source hier vielleicht komplett pasten?

Danke und Grüße

Stanlay Hanks 29. Okt 2005 13:15

Re: for...in...do für COM Collections
 
Probier einfach ein paar mal F5. Hin und wieder kommt man drauf ;)

sakura 29. Okt 2005 13:20

Re: for...in...do für COM Collections
 
Zitat:

Zitat von Lemmy1
Komme nicht auf Quality Central (ist wohl down). Könntest Du den Source hier vielleicht komplett pasten?

Ist vielleicht gerade etwas schade, dass CC (Code Central ;)) gerade offline ist, aber ich habe den auch gerade nicht hier. Einfach mal warten :?

...:cat:...

Lemmy1 29. Okt 2005 14:02

Re: for...in...do für COM Collections
 
Habs via Google Cache geschafft. Tolles Teil Sakura! Das werde ich sicher noch oft brauchen.

Danke und Grüße


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:11 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz