AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Property via AsString;AsInteger;AsBoolean;.. laden

Ein Thema von -=ZGD=- · begonnen am 23. Aug 2012 · letzter Beitrag vom 24. Aug 2012
Antwort Antwort
Seite 1 von 2  1 2      
-=ZGD=-

Registriert seit: 25. Apr 2006
Ort: Bad Aibling
105 Beiträge
 
Delphi 10.1 Berlin Professional
 
#1

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 09:49
Warum hilft dir die Antwort von mkinzler nicht weiter? Es ist nämlich die einzige Lösung die genau zu dem gewünschten Verhalten führt.
Weil "ja" mir nicht ausreichend war

Deine Items müssten als Objekte in einem Array oder in einer Liste verwaltet werden. Dann könntest du über myConfig.Items['dbport'].WasAuchImmer auf die Methoden und Propertys zugreifen. Und du müsstest nur noch pro Datentyp eine Property mit entsprechender Getter Methode bereitstellen.
Das wäre eigentlich genau mein Plan. Dann muss ich mit einer ObjectList arbeiten?

Alternativ könntest du auch weitere Propertys in deiner Config Klasse machen. Ungefähr so property ItemsAsInteger[aKey: String]: Integer read GetIntegerValue write SetIntegerValue; .

Aber du wirst zu jedem Datentyp eine Property samt Getter Methode schreiben müssen, welche sich dann um die Typumwandlung kümmert.
Hmm, auf diese Methode bin ich noch gar nicht gekommen. Der Implementierungsaufwand wäre in beiden Fällen der Gleiche...
Ich danke dir - einstweilen..
Stefan Michalk
  Mit Zitat antworten Zitat
bepe

Registriert seit: 17. Okt 2006
119 Beiträge
 
#2

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 10:00
Weil "ja" mir nicht ausreichend war
Das hab ich mir fast gedacht Wollte eigentlich wissen wie ausführlich ich antworten sollte... Aber wenn du erst einmal weiter kommst, ist ja alles gut.

Die Variante mit den Objekten wäre meiner Meinung nach "schöner". Aber ist auch mit mehr Tipparbeit verbunden.

Die ObjectList wäre wohl eine gute Lösung. Aber es gibt (zumindest je nach Delphi Version) mehrere Ansätze. Da deine Items Namen haben, würde sich z.B. auch ein TDictionary anbieten.

mfg,
bp
  Mit Zitat antworten Zitat
-=ZGD=-

Registriert seit: 25. Apr 2006
Ort: Bad Aibling
105 Beiträge
 
Delphi 10.1 Berlin Professional
 
#3

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 10:01
So sieht es jetzt bei mir aus

Ich habe ein record über alle Einträge:
Delphi-Quellcode:
type
  RConfig = record
    Key: String;
    Value: String;
  end;
Daraus einen eigenen Typ, als dynamisches Array

Delphi-Quellcode:
type
  TConfigList = array of RConfig;
Welches Verwendung in der Klassendeklaration
Delphi-Quellcode:
type
  TConfig = class(TObject)
  private
    Con: TZConnection;
    Query: TZQuery;

    fNewDB: Boolean;

    fList: TConfigList;

    function GetValue(aID: String): String;
    procedure SetValue(aID: String; aValue: String = '');
    function getItemCount: Integer;
  public
    constructor create;

    property IsNew: Boolean read fNewDB;
    property Items[aKey: String]: String read GetValue write SetValue;
    property Count: Integer read getItemCount;
    procedure ReadConfig;
    function Exists(aKey: String): Boolean;
    function save: Boolean;
  end;
in der privaten Variable fList Anwendung findet.

Wie würde jetzt meine Deklaration aussehen, wenn ich die Items als Objekt handhaben möchte.

Meine Idee wäre dann

Delphi-Quellcode:
type
  TConfigItem = class(TObject)
  private
    function GetAsInteger: Integer;
    function GetAsString: String;
  public
    property AsInteger: Integer read GetAsInteger;
    property AsString: String read GetAsString;
  end;
Woraus sich ergeben würde, dass Items[aKey: String]: TConfigItem wird.
Allerdings mit welchem read ?
Stefan Michalk
  Mit Zitat antworten Zitat
bepe

Registriert seit: 17. Okt 2006
119 Beiträge
 
#4

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 10:18
So sieht es jetzt bei mir aus

Ich habe ein record über alle Einträge:
Delphi-Quellcode:
type
  RConfig = record
    Key: String;
    Value: String;
  end;
Daraus einen eigenen Typ, als dynamisches Array

Delphi-Quellcode:
type
  TConfigList = array of RConfig;
Soweit, so gut. Du brauchst jedoch nicht Objekt und Record. Du verwendest XE2? Dann kannst du in deinem Record Propertys deklarieren, wie du es auch in einem Objekt machen würdest.
Welches Verwendung in der Klassendeklaration
Delphi-Quellcode:
type
  TConfig = class(TObject)
  private
    Con: TZConnection;
    Query: TZQuery;

    fNewDB: Boolean;

    fList: TConfigList;

    function GetValue(aID: String): String;
    procedure SetValue(aID: String; aValue: String = '');
    function getItemCount: Integer;
  public
    constructor create;

    property IsNew: Boolean read fNewDB;
    property Items[aKey: String]: String read GetValue write SetValue;
    property Count: Integer read getItemCount;
    procedure ReadConfig;
    function Exists(aKey: String): Boolean;
    function save: Boolean;
  end;
in der privaten Variable fList Anwendung findet.

Wie würde jetzt meine Deklaration aussehen, wenn ich die Items als Objekt handhaben möchte.

Meine Idee wäre dann

Delphi-Quellcode:
type
  TConfigItem = class(TObject)
  private
    function GetAsInteger: Integer;
    function GetAsString: String;
  public
    property AsInteger: Integer read GetAsInteger;
    property AsString: String read GetAsString;
  end;
Wie erwähnt, du kannst die Funktionen und Propertys einfach ins Record verschieben und brauchst die Klasse nicht mehr. Aber ansonsten korrekt umgesetzt (wenn du nur lesend auf die Werte zugreifen möchtest).

Woraus sich ergeben würde, dass Items[aKey: String]: TConfigItem wird.
Allerdings mit welchem read ?
An der Deklaration von Items ändert sich, außer dem Typ, nichts. Also so wie du es gemacht hast*. Im read änderst du auch nur den Typ und greifst natürlich auf dein TConfigList array zu.

*Wenn du das Objekt entfernst und nur mit dem Record arbeitest, sehe Items so aus Items[aKey: String]: RConfig

mfg,
bp
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#5

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 10:53
Schau dir dazu vielleicht auch mal die Operator-Überladung an, im speziellen Implicit. Damit bräuchtest du dann dieses AsString oder AsInteger nicht. Der Konvertierung würde dann alles automatisch funktionieren.

Besser für Refactoring wäre es, wenn du entsprechende Properties nutzen würdest. So handhabe ich das ganze -- momentan gibts den Code nur in VB.Net, portiere den aber bald nach Delphi:
Delphi-Quellcode:
// Habe die Property mal aufs Minimum reduziert
TXmlConfigurationNodeAttribute = class(TAttribute)
public
  property Path : string read GetPath;
end;

TBaseConfiguration = abstract class
protected
  FXmlPathToPropertyIndex : IDictionary<string, TRttiProperty>;
  
  // Diese Methode baut einen Index aus Pfad-zu-Property
  // Wertpaaren auf, welcher dann in der LoadConfiguration
  // genutzt wird
  procedure ReadXmlProperties();
public
  // Diese Methode liest aus dem XML-Node die entsprechenden
  // Daten aus und setzt die gelesenen Werte via RTTI auf die
  // entsprechenden Properties. Natürlich wird dabei eine
  // Konvertierung der Datentypen vorgenommen.
  procedure LoadConfiguration(XmlNode: IXmlNode);
end;

// Die Methode ist nur schnell hingeschrieben, die Idee soll
// rüberkommen!
procedure TBaseConfiguration.LoadConfiguration(XmlNode: IXmlNode);
begin
  for PathPropertyPair in FXmlPathToPropertyIndex
  begin
    Path := PathPropertyPair.Key;
    Property := PathPropertyPair.Value;
    Value := GetValueFromXml(XmlNode, Path);
    Property.SetValue(Self, Convert(Value, Property));
  end;
end;

// So, was bringt das nun? Je Anwendung brauche ich dann nur noch
// eine abgeleitete Klasse schreiben, die minimalen Code enthält,
// aber dennoch dafür sorgt, dass alles passt und dazu auch noch
// wunderbar typsicher ist.
TMyConfiguration = class(TBaseConfiguration)
public
  [XmlConfigurationNode('ftp-server/host')]
  property Host : string read FHost write SetHost;

  [XmlConfigurationNode('ftp-server/port')]
  property Port : Integer read FPort write SetPort;
end;
Vielleicht findest die Idee ja interessant
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#6

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 10:57
Wie wäre es mit dem Typ Variant als Ergebnis? Dann übernimmt Delphi die komplette Typ-Konvertierung (dort, wo es geht) und man spart sich viel Schreibarbeit:
Delphi-Quellcode:
type
  TMyClass = class
  private
    procedure SetItem(const Name: String; const Value: Variant);
    function GetItem(const Name: String): Variant;
  public
    property Items[const Name: String]: Variant read GetItem write SetItem;
  end;
Thomas Nitzschke
Google Maps mit Delphi
  Mit Zitat antworten Zitat
-=ZGD=-

Registriert seit: 25. Apr 2006
Ort: Bad Aibling
105 Beiträge
 
Delphi 10.1 Berlin Professional
 
#7

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 11:02
Wie wäre es mit dem Typ Variant als Ergebnis? Dann übernimmt Delphi die komplette Typ-Konvertierung (dort, wo es geht) und man spart sich viel Schreibarbeit:
Delphi-Quellcode:
type
  TMyClass = class
  private
    procedure SetItem(const Name: String; const Value: Variant);
    function GetItem(const Name: String): Variant;
  public
    property Items[const Name: String]: Variant read GetItem write SetItem;
  end;
Hallo Thom,

das würde funktionieren, ist aber insofern unpraktisch, dass ich gern vordefinierte Werte zurückgeben möchte.

Wenn ich beispielsweise einen Port (INTEGER) zuweise und die
Code:
Value
leer ist, beschmeißt mich Delphi natürlich mit der korrekten Fehlermeldung
Code:
"" ist kein gültiger Integer-Wert
. Das würde ich umgehen wollen und einfach von vorn herein
Code:
0
übergeben.
Stefan Michalk
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#8

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 11:12
Hast meinen Post oben schon gesehen?

Default-Werte solltest du im Konstruktor setzen. Dafür ist er da.

Und warum denn bitte Variant nehmen? Die ganze Typsicherheit geht verloren und du bekommst erst zur Laufzeit Probleme, da der Compiler die Typen nicht schon beim Compilieren prüfen kann.
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#9

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 11:17
@-=ZGD=-:

Gut, dann müßtest Du natürlich vorher den Inhalt des Variant-Wertes testen:
Delphi-Quellcode:
  if VarIsType(Items['xxx'],varInteger)
    then IntegerWert:=Items['xxx']
    else IntegerWert:=IntegerDefault;
Willst Du diesen Test innerhalb Deines Objektes unterbringen, ist die Verwendung von Variant ungünstig und ich würde an Deiner Stelle auch Records nehmen.

Und warum denn bitte Variant nehmen? Die ganze Typsicherheit geht verloren und du bekommst erst zur Laufzeit Probleme, da der Compiler die Typen nicht schon beim Compilieren prüfen kann.
Dafür gibt es Tests... Und es gibt Sprachen, die bauen ausschließlich auf Variant auf (z.B. JavaScript).
Thomas Nitzschke
Google Maps mit Delphi

Geändert von Thom (23. Aug 2012 um 11:19 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#10

AW: Property via AsString;AsInteger;AsBoolean;.. laden

  Alt 23. Aug 2012, 11:19
Warum es erst zur Laufzeit krachen lassen, wenn mir schon der Compiler sagen kann, dass das was schief laufen wird? Läuft doch nur darauf hinaus, dass ich jeden Käse abfragen muss, bevor ich dann die eigentliche Variable nutzen kann. Und den Vorteil von den Variants sehe ich dann einfach nicht, tut mir Leid. Zudem erzeugst du so eher mehr Code und Unsicherheit, was es doch nicht brauch.

Zudem stell dir mal die Situation vor, dass ein Kollege deinen Code nutzen will und nicht weiß, was er denn für Daten bekommt. Ist der Wert von der "Variable" Index nun vom Type string oder Integer? Oder gar ganz was anderes. Was soll er denn mit Variant anfangen können? Erst mal die komplette Doku lesen, obwohl IntelliSense ihm sagen könnte "Hey, Index ist vom Typ string".
Zitat:
Dafür gibt es Tests... Und es gibt Sprachen, die bauen ausschließlich auf Variant auf (z.B. JavaScript).
Nur weil es Sprachen gibt, die darauf aufbauen -- wobei ich nicht wirklich weiß, wie JS das handhabt -- heißt es ja auch noch lange nicht, dass es gut ist. JavaScript und PHP haben mich oft genug mit diesem varianten Gehabe gestört. Wenn ich auf einmal aus einem string eine Klasse generieren kann, ist das vielleicht schon recht nett, aber man läuft echt in viele Probleme rein. Typsicherheit bringt auf jedenfall mehr Aufbau, sichert aber eben auch sehr viel zu, auf das man sich verlassen kann.
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)

Geändert von s.h.a.r.k (23. Aug 2012 um 11:25 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 13:38 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz