![]() |
Property via AsString;AsInteger;AsBoolean;.. laden
Servus,
ich stehe vor einem kleinen Problem und komm leider auch trotz Suche nicht auf die richtigen Stichwörter. Ich bin mir sicher, dieses Problem wurde schon öfter mal angesprochen. Problem Ich habe eine Konfigurationsklasse, in welcher wie gesagt Einstellungen auf Vorrat gehalten werden. Das Lesen/Schreiben via
Delphi-Quellcode:
in dem einfach der Schlüssel übergeben wird funktioniert problemlos.
property Items[aKey: String]: String read GetValue write SetValue;
Ich möchte jetzt aber nicht ständig Typenumwandlungen machen und daher ist meine Fragen: Wie kann ich es lösen, dass der Aufruf
Delphi-Quellcode:
genügen würde und ich den Port als
myConfig.Items['dbport'].AsInteger
Delphi-Quellcode:
erhalten?
Integer
Über Links und Hilfestellung jeder Art bin ich dankbar. Auch wenn wie ![]() Ich danke vielmals. |
AW: Property via AsString;AsInteger;AsBoolean;.. laden
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.
Deine Items müssten als Objekte in einem Array oder in einer Liste verwaltet werden. Dann könntest du über
Delphi-Quellcode:
auf die Methoden und Propertys zugreifen. Und du müsstest nur noch pro Datentyp eine Property mit entsprechender Getter Methode bereitstellen.
myConfig.Items['dbport'].WasAuchImmer
Alternativ könntest du auch weitere Propertys in deiner Config Klasse machen. Ungefähr so
Delphi-Quellcode:
.
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. |
AW: Property via AsString;AsInteger;AsBoolean;.. laden
Zitat:
Zitat:
Zitat:
Ich danke dir - einstweilen.. |
AW: Property via AsString;AsInteger;AsBoolean;.. laden
Zitat:
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
Delphi-Quellcode:
anbieten.
TDictionary
|
AW: Property via AsString;AsInteger;AsBoolean;.. laden
So sieht es jetzt bei mir aus
Ich habe ein
Delphi-Quellcode:
über alle Einträge:
record
Delphi-Quellcode:
Daraus einen eigenen Typ, als dynamisches Array
type
RConfig = record Key: String; Value: String; end;
Delphi-Quellcode:
Welches Verwendung in der Klassendeklaration
type
TConfigList = array of RConfig;
Delphi-Quellcode:
in der privaten Variable
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;
Delphi-Quellcode:
Anwendung findet.
fList
Wie würde jetzt meine Deklaration aussehen, wenn ich die
Delphi-Quellcode:
als Objekt handhaben möchte.
Items
Meine Idee wäre dann
Delphi-Quellcode:
Woraus sich ergeben würde, dass
type
TConfigItem = class(TObject) private function GetAsInteger: Integer; function GetAsString: String; public property AsInteger: Integer read GetAsInteger; property AsString: String read GetAsString; end;
Delphi-Quellcode:
wird.
Items[aKey: String]: TConfigItem
Allerdings mit welchem
Delphi-Quellcode:
?
read
|
AW: Property via AsString;AsInteger;AsBoolean;.. laden
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
änderst du auch nur den Typ und greifst natürlich auf dein
read
Delphi-Quellcode:
array zu.
TConfigList
*Wenn du das Objekt entfernst und nur mit dem Record arbeitest, sehe Items so aus
Delphi-Quellcode:
Items[aKey: String]: RConfig
|
AW: Property via AsString;AsInteger;AsBoolean;.. laden
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:
Vielleicht findest die Idee ja interessant :)
// 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; |
AW: Property via AsString;AsInteger;AsBoolean;.. laden
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; |
AW: Property via AsString;AsInteger;AsBoolean;.. laden
Danke für dein Hilfe bepe.
Auf Grundlage deiner Informationen bin ich jetzt soweit vorangeschritten:
Delphi-Quellcode:
Die Implementierung der GET/SET
type
RConfig2 = record private fKey: String; fValue: Variant; function GetAsString: String; function GetAsInteger: Integer; public property Key: String read fKey write fKey; property Value: Variant write fValue; property AsString: String read GetAsString; property AsInteger: Integer read GetAsInteger; end;
Delphi-Quellcode:
function RConfig2.GetAsString;
begin result := STRING(fValue); end; function RConfig2.GetAsInteger; var val: Integer; begin if TryStrToInt(fValue, val) then begin result := val end else raise Exception.Create('Konvertierungsfehler - Kein INTEGER'); end; Daraus ergab sich eine neue Liste
Delphi-Quellcode:
type
TConfigList2 = array of RConfig2; Was im Objekt an sich zu folgenden Änderungen führt:
Delphi-Quellcode:
type
TConfig = class(TObject) private ... fList: TConfigList; fList2: TConfigList2; ... function GetVariantValue(aID: String): RConfig2; procedure SetVariantValue(aID: string; aValue: Variant); ... public constructor create; ... property Item[aKey: String]: RConfig2 read GetVariantValue write SetVariantValue; ... end;
Delphi-Quellcode:
sieht nun bei mir so aus (ja, noch keine Hashtable)
GetVariantValue
Delphi-Quellcode:
Ich dachte mir, ich nehme
function TConfig.GetVariantValue(aID: string): RConfig2;
var i: Integer; begin ReadConfig; for i := low(fList2) to high(fList2) do begin if uppercase(fList2[i].Key) = uppercase(aID) then begin Result := fList2[i]; break; end; end; end;
Delphi-Quellcode:
als Typ für die Value, denn somit bin ich da flexibel...eher ungut?
Variant
Woran ich jetzt allerdings scheitere ist die Implementierung von
Delphi-Quellcode:
.
SetVariantValue
Der Compiler sagt
Code:
.
Inkompatible Typen
Delphi-Quellcode:
Den Versuch, einfach ein
procedure Tconfig.SetVariantValue(aID: string; aValue: Variant);
begin end;
Code:
zu übergeben ist ebenfalls gescheitert.
RConfig2
Wo seh ich den Wald vor lauter Bäumen nicht? Ist die Implementierung in den Grundzügen so korrekt? |
AW: Property via AsString;AsInteger;AsBoolean;.. laden
Zitat:
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:
leer ist, beschmeißt mich Delphi natürlich mit der korrekten Fehlermeldung
Value
Code:
. Das würde ich umgehen wollen und einfach von vorn herein
"" ist kein gültiger Integer-Wert
Code:
übergeben.
0
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:09 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 by Thomas Breitkreuz