Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Dynamisch Klassenfelder mit Superobjects füllen (https://www.delphipraxis.net/201710-dynamisch-klassenfelder-mit-superobjects-fuellen.html)

Blackpit 18. Aug 2019 22:40

Dynamisch Klassenfelder mit Superobjects füllen
 
Hallo,
ich komm nicht weiter mit einer KlassenProzedur, welche mittels Superobject
Daten von einem WS zieht. Ich würde die IndexfromString-Lösung gerne dynamisch gestalten, um nur noch die Klassenfelder bei Bedarf zu ergänzen.
Meine verzweifelten Bemühungen als Kommentar ;)
Class:

Delphi-Quellcode:
  TProjectComponents = class
  public
    component1 : Boolean;
    component1 : Boolean;
    component1 : Boolean;
    component1 : Boolean;
    component1 : Boolean;
    function writeToJson():String;
    procedure readFromJson(aJsonString: String);
  end;
Prozedur:

Delphi-Quellcode:
procedure TProjectComponents.readFromJson(aJsonString: String);
var
  json: ISuperObject;
  iterate: TSuperAvlIterator;
  components: ISuperObject;
begin

  try
  json := SO(aJsonString);
  iterate := json.AsObject.GetEnumerator;
  iterate.First;
  while iterate.MoveNext do
  begin
  // ClassField(iterate.Current.Name) := iterate.Current.Value.b['active'];
  // Format('s%',[iterate.Current.Name]) := iterate.Current.Value.b['active'];
  //components := json;
  //components.N[Format('s%',[iterate.Current.Name])] := iterate.Current.Value.b['active'];
    case IndexStr(iterate.Current.Name,['component1','component2','component3','component4','component5'])of
      0: component1 := iterate.Current.Value.b['active'];
      1: component2 := iterate.Current.Value.b['active'];
      2: component3 := iterate.Current.Value.b['active'];
      3: component4 := iterate.Current.Value.b['active'];
      4: component5 := iterate.Current.Value.b['active'];
    end;
  end;
  iterate.Free;
  finally
    json := nil;
  end;

end;
Kann mir jemand helfen?

hoika 19. Aug 2019 07:53

AW: Dynamisch Klassenfelder mit Superobjects füllen
 
Hallo,
du willst den Code
0: component1 := iterate.Current.Value.b['active'];
1: component2 := iterate.Current.Value.b['active'];

allgemeiner halten?

Was du wahrscheinlich suchst, ist RTTI.
Dazu müssten die betreffenden Variablen published statt public sein. (Soweit ich weiss)

Neutral General 19. Aug 2019 08:50

AW: Dynamisch Klassenfelder mit Superobjects füllen
 
Die "neue" RTTI liest auch public und soweit ich weiß sogar protected und private Properties/Felder/Methoden aus.

Schokohase 19. Aug 2019 08:58

AW: Dynamisch Klassenfelder mit Superobjects füllen
 
Man könnte auch mit einem Dictionary arbeiten und dieses direkt verwenden oder auch indirekt
Delphi-Quellcode:
TProjectComponents = class
private
  FComponents: TDictionary<string,boolean>;
  function GetComponent1:Boolean;
public
  property Component1: Boolean read GetComponent1;
end;

function TProjectComponents.GetComponent1: Booelan;
var
  val: Boolean;
begin
  Result := FComponents.TryGetValue('component1', val ) and val;
end;

Blackpit 19. Aug 2019 10:19

AW: Dynamisch Klassenfelder mit Superobjects füllen
 
Ups, die Klassendefinition sollte natürlich so aussehen:

Delphi-Quellcode:
  TProjectComponents = class
  public
    component1 : Boolean;
    component2 : Boolean;
    component3 : Boolean;
    component4 : Boolean;
    component5 : Boolean;
    function writeToJson():String;
    procedure readFromJson(aJsonString: String);
  end;
Danke schon mal für die Hinweise, den Dictionary-Vorschlag versuch ich mal umzusetzten. Mit RTTI muss ich mich erst mal auseinandersetzen.

Blackpit 19. Aug 2019 15:18

AW: Dynamisch Klassenfelder mit Superobjects füllen
 
Die Idee mit dem Dictionary fand ich gut, bekomme es aber nicht hin.
Der Gedanke war das Dictionary flexibel zu füllen, so sieht mein Versuch aus:
Delphi-Quellcode:
   TProjectComponents = class
  public
    Components: TDictionary<string,boolean>;//
    function getComponents(aJsonString: String) : TDictionary<string,boolean>;
   // function writeToJson():String;
    procedure readFromJson(aJsonString: String);
  end;

procedure TProjectComponents.readFromJson(aJsonString: String);
var
  json: ISuperObject;
begin
  json := SO(aJsonString);
  bookableFeature := getComponents(aJsonString);
end;

function getComponents(aJsonString: String) : TDictionary<string,boolean>;
var
  val: Boolean;
  json: ISuperObject;
  iterate: TSuperAvlIterator;
  Components :TDictionary<string,boolean>;
begin
  try
  json := SO(aJsonString);
  iterate := json.AsObject.GetEnumerator;
  iterate.First;
  while iterate.MoveNext do
  begin
   Components.Add(iterate.Current.Name, iterate.Current.Value.b['active']);
   //Components.TryGetValue(iterate.Current.Name, val ) and val;
  end;
  iterate.Free;
  finally
    json := nil;
  end;
  Result := Components;
end;
Beim Add kommt eine AV die ich mir nicht erklären kann, im Debugger stehen die richtigen Werte als String und Bool.
Was mach ich falsch?

Schokohase 19. Aug 2019 15:26

AW: Dynamisch Klassenfelder mit Superobjects füllen
 
Delphi-Quellcode:
TDictionary<TKey,TValue>
ist eine Klasse und du erzeugst nirgends eine Instanz.

Blackpit 19. Aug 2019 15:36

AW: Dynamisch Klassenfelder mit Superobjects füllen
 
Ist mir auch gerade aufgefallen, so funktionierts:
Delphi-Quellcode:
function getComponents(aJsonString: String) : TDictionary<string,boolean>;
var
  json: ISuperObject;
  iterate: TSuperAvlIterator;
  Components :TDictionary<string,boolean>;
begin
  try
  json := SO(aJsonString);
  Components:=TDictionary<string,boolean>.create;
  iterate := json.AsObject.GetEnumerator;
  while iterate.MoveNext do
  begin
   Components.Add(iterate.Current.Name, iterate.Current.Value.b['active']);
  end;
  iterate.Free;
  finally
    json := nil;
  end;
  Result := Components;
end;
Danke für's helfen!


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:55 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