AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Delphi for...in...do für COM Collections
Tutorial durchsuchen
Ansicht
Themen-Optionen

for...in...do für COM Collections

Ein Tutorial von sakura · begonnen am 19. Dez 2004 · letzter Beitrag vom 29. Okt 2005
Antwort Antwort
Benutzerbild von sakura
sakura
Registriert seit: 10. Jun 2002
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.
Ich bin nicht zurück, ich tue nur so
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#2
  Alt 19. Dez 2004, 19:20
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.
Daniel W.
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#3
  Alt 19. Dez 2004, 19:31
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.
Daniel W.
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#4
  Alt 19. Dez 2004, 19:37
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);
Daniel W.
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#5
  Alt 19. Dez 2004, 19:38
Der Quellcode für den COM Enumerator könnt Ihr in der Borland CodeCentral unter dem Eintrag 22263 finden und runterladen.

Viel Spaß damit!

......
Daniel W.
  Mit Zitat antworten Zitat
Benutzerbild von Lemmy1
Lemmy1

 
Delphi 2006 Professional
 
#6
  Alt 29. Okt 2005, 13:12
Komme nicht auf Quality Central (ist wohl down). Könntest Du den Source hier vielleicht komplett pasten?

Danke und Grüße
Daniel
  Mit Zitat antworten Zitat
Benutzerbild von Stanlay Hanks
Stanlay Hanks

 
Delphi 2005 Professional
 
#7
  Alt 29. Okt 2005, 13:15
Probier einfach ein paar mal F5. Hin und wieder kommt man drauf
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#8
  Alt 29. Okt 2005, 13:20
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

......
Daniel W.
  Mit Zitat antworten Zitat
Benutzerbild von Lemmy1
Lemmy1

 
Delphi 2006 Professional
 
#9
  Alt 29. Okt 2005, 14:02
Habs via Google Cache geschafft. Tolles Teil Sakura! Das werde ich sicher noch oft brauchen.

Danke und Grüße
Daniel
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:17 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