![]() |
Record- oder Klassenfelder als property zuweisen und lesen, wie?
Hallo,
bitte guckt nicht zu sehr auf meine Ausdrucksweise, ich weiß echt nicht weiter. Fragestellung unten.
Delphi-Quellcode:
Wie kann ich jetzt mein Item in TCustomColumn lesen und schreiben, ohne dass Exceptions geworfen werden.
{ TDataItem }
TDataItem = record DataType: TDataType; Field1: Typ1; Field2: Typ2; //Für mehrere Datenfelder Fieldnum: Integer; //Feldnummer case Longword of 0: (BinData : Pointer); //für binäre Daten 1: (dworddata: Longword); //für ganzzahlige positive Zahlenwerte 2: (Int32data: Integer); //für ganzzahlige positive wie negative Zahlenwerte 3: (Floatdata: Double); //für Gleitkommazahlen 4: (Int16data: smallint); //für 16 Bit Integerzahlen 5: (Strgdata : PString); //für Strings end; { TGenericItem } TGenericItem = class(TObject) private FData: TDataItem; function GetDataType: TDataType; function GetData: TDataItem; procedure SetDataType(AValue: TDataType); procedure SetData(AValue: TDataItem); public constructor Create; destructor Destroy; override; property Data: TDataItem read GetData write SetData; end; { TCustomColumn } TCustomColumn = class(TComponent) private FLeft: Integer; FTop: Integer; FItem: TGenericItem; procedure SetItem(AValue: TGenericItem); public constructor Create(AOwner: TComponent); property [B]Item[/B]: TGenericItem read FItem write SetItem; end;
Delphi-Quellcode:
Wie kann ich bei zusammengesetzten Typen die Daten als Eigenschaft lesen uns schreiben. Sorry, ich weiß echt nicht wie ich es anders ausdrücken soll.
function TGridColumn.GetWidth: Integer;
var AItem: TDataItem; begin AItem := Item.Data; //das hier wird nicht akzeptiert, wie mache ich das besser? Wenn ich an die Eigenschaft nur den ganzen Datentyp zuweisen kann, brauche ich ja die Daten der übrigen Felder //die hier nicht beeinflusst werden. Ok, beim Getter nicht aber beim Setter. Result := AItem.Fieldnum; //sowas in der Art will ich am Ende haben, für alle im Datentyp enthaltenen Felder end; Am Ende will ich Record- und Klassentypen als property lesen und schreiben und dabei auch einzelne Datenfelder dieser Typen verändern können, wie im Beispiel die Fieldnum oder die Inhalte von Field1 und Field2, wobei ich als Interface nur die property mit dem gesamten Datentyp habe, der die Felder enthält. |
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Alles zu kompliziert. Ich baue solche Felder grundsätzlich direkt in meine Klasse ein, vermeide solche komplexen Konstrukte.
|
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Mit einem Pointer auf TDataItem, den die Property zurück liefert, sollte es gehen.
Ich persönlich würde das ganze aber komplett mit Generics und Klassen umsetzen. Mal so ins Blaue getippt, das sollte kompilieren:
Delphi-Quellcode:
Alternativ:
type
TDataItem = class end; TDataItem<T> = class(TDataItem) private FData: T; public constructor Create(const AValue: T); procedure SetData(const AValue: T); function GetData: T; end; TCustomColumn = class(TComponent) private FItem: TDataItem; public procedure SetItem<T>(const AValue: T); function GetItem<T>: T; end; ... function TCustomColumn.GetItem<T>: T; begin if Assigned(FItem) and (FItem is TDataItem<T>) then Result := TDataItem<T>(FItem).GetData else raise Exception.Create('Falscher Typ'); end; procedure TCustomColumn.SetItem<T>(const AValue: T); begin FItem.Free; FItem := TDataItem<T>.Create(AValue); end; constructor TDataItem<T>.Create(const AValue: T); begin FData := AValue; end; function TDataItem<T>.GetData: T; begin Result := FData; end; procedure TDataItem<T>.SetData(const AValue: T); begin FData := AValue; end; ... procedure Example; var a: TCustomColumn; begin a := TCustomColumn.Create(nil); a.SetItem<Integer>(42); ShowMessage(a.GetItem<Integer>.ToString); a.SetItem<string>('42'); ShowMessage(a.GetItem<string>); end;
Delphi-Quellcode:
function TCustomColumn.GetItem<T>: T;
begin if Assigned(FItem) then Result := (FItem as TDataItem<T>).GetData else Result := TValue.Empty.AsType<T>; end; |
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Denke ich zu einfach? Bei mir funkt es ...
Delphi-Quellcode:
function TTemplateApp.GetWidth: Integer;
var LoColumn : TCustomColumn; LoDataItem: TGenericItem; begin Result := 0; LoColumn := TCustomColumn.Create(nil); LoDataItem := TGenericItem.Create; try LoColumn.Item := LoDataItem; Result := LoColumn.Item.Data.Int32data; finally FreeAndNil(LoDataItem); FreeAndNil(LoColumn); end; end; |
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Zitat:
|
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Verstehe, es geht um die Zuweisung. Das habe ich im Anfangsbeispiel nicht gesehen.
Ein Interimsrecord tut's auch.
Delphi-Quellcode:
function TTemplateApp.GetWidth: Integer;
var LoColumn : TCustomColumn; LoDataItem: TGenericItem; LrData : TDataItem; begin Result := 0; LoColumn := TCustomColumn.Create(nil); LoDataItem := TGenericItem.Create; try // Speicherschutz LoColumn.Item := LoDataItem; LrData := LoDataItem.Data; LrData.Int32data := 42; LoDataItem.Data := LrData; Result := LoColumn.Item.Data.Int32data; finally // aufräumen FreeAndNil(LoDataItem); FreeAndNil(LoColumn); end; end; |
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Das erfüllt die Anforderung nicht so ganz:
Zitat:
|
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Danke @jaenicke, da werd ich das mal so umsetzen, wie in Beitrag #3, das compiliert. Bei Fragen oder endgültig gefundener Lösung melde ich mich wieder. Da werd ich mich also nun mal mit Generics beschaäftigen.
@ConnorMcLeod: so wollte ich das ja zuerst machen, funkt aber bei mir nicht. |
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Gut, wenn die Lösung paßt. Ich bin auch ein Freund von Pointern. Aber die Dereferenziererei und Casterei verlangt eiserne Disziplin ;-)
|
AW: Record- oder Klassenfelder als property zuweisen und lesen, wie?
Zitat:
Delphi-Quellcode:
type
PDataItem = ^TDataItem; ... type TGenericItem = class(TObject) private FData: TDataItem; ... property Data: PDataItem read GetData; ... function TGenericItem.GetData: PDataItem; begin Result := @FData; end; ... var Item: TGenericItem; ... if Item.Data.Fieldnum < 0 then Item.Data.FieldNum := 1; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:24 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