Hallo marabu
Ich würde gern den Code reinstellen, nur geht es nicht, da ich auf einen Web-Service zugreife.
In den Code-Bsp. stellt
Zitat:
TBlaBla = class(irgenetwas)
das Objekt da, welches ich
über den Web-Service bekomme. Es hat ca. 25 einfache Eigenschaften wie WideString, TXSDateTime, Boolean usw.,
aber auch ca. 30 Eigenschaften die alle vom Type: Array of sind. In den Array of werden weitere Objekte
referenziert, je nach bedarf.
Nun wollte ich dynamisch die Eigenschaften durchgehen um nur die Elemente in einer Liste zu speichern
in denen tatsächlich auch Werte enthalten sind.
Beispielhaft etwa so:
Delphi-Quellcode:
unit uMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ExtCtrls, StdCtrls, Contnrs, BlaObject;
type
TForm1 =
class(TForm)
Panel1: TPanel;
Button1: TButton;
Panel2: TPanel;
tvData: TTreeView;
Splitter1: TSplitter;
lvData: TListView;
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
FRootNode : TTreeNode;
procedure InsertListData(List : TObjectList);
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses uTools;
procedure TForm1.InsertListData(List : TObjectList);
var
I : Integer;
SE : TSoapEntry;
begin
for I := 0
to List.Count -1
do
begin
SE := TSoapEntry(List.Items[I]);
tvData.Items.AddChild(FrootNode, SE.
Name);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
UObject : TBlaObject;
List : TObjectList;
begin
UObject := TBlaObject.Create;
try
List := TObjectList.Create;
try
FRootNode := tvData.Items.Add(
nil, UObject.ClassName);
if GetObjectData(UObject, List)
then InsertListData(List);
finally
List.Free;
end;
finally
UObject.Free;
end;
end;
end.
Unit zur Ermittlung der Eigenschaften:
Delphi-Quellcode:
unit uTools;
interface
uses Windows, SysUtils, Classes, Variants, Contnrs, TypInfo,
BlaObject;
//<- Webservice
type
// Dient zum Zwischenspeichern
TSoapEntry =
class
Name :
String;
SoapTyp : TVarType;
Value : Variant;
List : TObjectList;
end;
function GetObjectData(AObject : TObject;
var List : TObjectList) : Boolean;
implementation
var
PropList : pPropList;
I, J, K : Integer;
SoapEntry : TSoapEntry;
PropValue : Variant;
PropArray :
Array of TBlaBla;
PropObject : TObject;
begin
PropList := AllocMem(SizeOf(PropList^));
try
I := 0;
J := GetPropList(AObject, PropList);
if (J <> 0)
and (PropList^[I] <>
nil)
then
begin
while (I < J)
do
begin
SoapEntry := TSoapEntry.Create;
SoapEntry.
Name := PropList^[i].
Name;
try
if POS('
Elem', PropList^[i].
Name) = 0
then // Die 'Arrays of' fangen alle mit 'Elem' an, ohne kommt es zur Exception
begin
PropValue := GetPropValue(AObject, PropList^[i].
Name);
// Hier Exception bei 'Array of'
SoapEntry.Value := PropValue;
SoapEntry.SoapTyp := TVarData(PropValue).VType;
end
else
begin // Nur ein weiter Versuch, der nicht zum Ziel führt
SoapEntry.SoapTyp := varArray;
SoapEntry.List := TObjectList.Create;
PropArray := @PropList^[i];
for K := 0
to High(PropArray)
do
begin
PropObject := TBlaBla(PropArray[K]);
GetObjectData(PropObject, SoapEntry.List);
// recursiver Aufruf der dann bei GetPropList scheitert
end;
end;
except
end;
if List.IndexOf(SoapEntry) = -1
then List.Add(SoapEntry)
else SoapEntry.Free;
Inc(I);
end;
end;
finally
FreeMem(PropList);
end;
Result := List.Count - 1 > -1;
end;
Das Objekt welches vom Web-Service kommt:
Delphi-Quellcode:
unit BlaObject;
interface
uses Windows, SysUtils, Classes;
type
ArrayOfString =
array of String;
TBlaBla =
class(TObject)
private
FQArray : ArrayOfString;
FSonst :
String;
published
property Sonst :
String read FSonst
write FSonst;
property QArray : ArrayOfString
read FQArray
write FQArray;
end;
ArrayOfBlaBla =
Array of TBlaBla;
TBlaObject =
class(TObject)
private
FAlleQArrays : ArrayOfBlaBla;
FDieses :
String;
published
property Dieses :
String read FDieses
write FDieses;
property AlleQArrays : ArrayOfBlaBla
read FAlleQArrays
write FAlleQArrays;
end;
...
implementation
end.
Wie geschrieben nur Beispielhaft, da der Code so nicht läuft(fehlende Initialisierung des 'webservices').
Ich hoffe ich habe mich klar ausgedrückt. Auch wenn einige nun vielleicht schreiben werden, dass ich es 'Statisch'
machen könnte/sollte, geht es nicht, da sich das Objekt vom Web-Service ändert und sich die Codeänderungen in der
Anwendung nur auf den Neuimport der WDSL-Datei beschränken soll.
Danke für die Mühe...
PS Falls noch Fragen sind fragen