![]() |
Generic record
Ich möchte mit Hilfe von GENERICS beliebige Records in ein ByteArray und wieder zurück umwandeln .
Für die Lösung wollte ich zum ersten mal GENERICS in Delphi verwenden. Der Code unten spielt wenn ich anstelle von TGenericRecord eine beliebige Record Definition direkt einsetze. Habe ich einen Denkfehler in meinem Ansatz ?
Delphi-Quellcode:
type TGenericRecord <TRecordType> = class /// value : TRecordType; end; /// /// --------------- HELPER FUNCTION FOR RECORD EXCHANGE ------------------ /// function MyRecordToByteArray(aRecord: TGenericRecord): TBytes; var LSource: PAnsiChar; begin LSource := PAnsiChar(@aRecord); SetLength(Result, SizeOf(TGenericRecord)); Move(LSource[0], Result[0], SizeOf(TGenericRecord)); end; function ByteArrayToMyRecord(ABuffer: TBytes): TGenericRecord; var LDest: PAnsiChar; begin LDest := PAnsiChar(@Result); Move(ABuffer[0], LDest[0], SizeOf(TGenericRecord)); end; |
AW: Generic record
Dein genric Record ist eine generic Class :shock:
TGenericRecord<x> entspricht nicht TGenericRecord
Delphi-Quellcode:
, da aber keine generischen Prozeduren möglich sind, muß dieses eine Methode eines Records oder eines Objekts werden.
function MyRecordToByteArray<X>(aRecord: TGenericRecord<x>): TBytes;
statt Zitat:
Zitat:
Zitat:
|
AW: Generic record
Ich glaub, du möchtest so etwas:
Delphi-Quellcode:
Denke aber bei diesem Ansatz auf jeden Fall daran, dass du damit keine managed types (z.B. string) behandeln kannst. Denn in dem Record befindet sich in diesem Fall nur ein Pointer auf den string.
type
TRecordSerializer = class class function ToByteArray<T: record>(const Value: T): TBytes; static; class function ToRecord<T: record>(const Value: TBytes): T; static; end; class function TRecordSerializer.ToByteArray<T>(const Value: T): TBytes; begin SetLength(Result, SizeOf(T)); Move(Value, Result[0], SizeOf(T)); end; class function TRecordSerializer.ToRecord<T>(const Value: TBytes): T; begin Move(Value[0], Result, SizeOf(T)); end; |
AW: Generic record
@ Stevie : in meinen records können leider auch Strings vorkommen .... kann damit Deine Lösung nicht verwenden
@ Himitsu : wenn ich keine Generic Typs als Funktions Rückgabewert verwenden kann --> dann muss ich wohl auf das gute & alte function overloading zurückgreifen :oops:; im Code unten maul der Compiler "TRecordType" kennt er nicht, ist doch klar.... kenne ich gerade selbst noch nicht .... sage ich dem Compiler schon und zwar dann wenn ich die Funktion auch verwenden will .... mit TGenericRecord<TAnwerndungsrecord>.Create, solange soll er halt warten
Delphi-Quellcode:
function MyRecordToByteArray(aRecord: TGenericRecord<TRecordType>): TBytes; var LSource: PAnsiChar; begin LSource := PAnsiChar(@aRecord); SetLength(Result, SizeOf(TMyRecord)); Move(LSource[0], Result[0], SizeOf(TGenericRecord<TRecordType>)); end; function ByteArrayToMyRecord(ABuffer: TBytes): TGenericRecord<TRecordType>; var LDest: PAnsiChar; begin LDest := PAnsiChar(@Result); Move(ABuffer[0], LDest[0], SizeOf(TGenericRecord<TRecordType>)); end; |
AW: Generic record
Zurückgeben kann man es, aber
Delphi-Quellcode:
ist nicht möglich ... das geht leider nur bei Methoden (Record oder Object).
function MyFunction<T>(...): ...;
|
AW: Generic record
was Delphi auf nicht compiliert :-(
Delphi-Quellcode:
type TRecordTypeA= .... .... ... .. // gib mir ein record type 1 zurück function testfunction (a : Integer) : TRecordTypeA; overload; // nun type 2 function testfunction (a : Integer) : TRecordTypeB; overload; // usw .... function testfunction (a : Integer) : TRecordTypeC; overload; müsste ich etwas wie
Delphi-Quellcode:
codieren.procedure (a : Integer; var TGenericRecordType<T> ); bzw. Zitat:
TGenericTRecord <TRecordtype>= class function ByteArrayToMyRecord(ABuffer: TBytes): TRecordtype end; |
AW: Generic record
Natürlich nicht.
Beim Überladen muß sich die Aufrufsignatur unterscheifen, also die Parameter müssen unterschiedlich sein. Bei dir sind sie aber gleich. Zitat:
Delphi-Quellcode:
// geht
TGenericTRecord<TRecordtype> = class function ByteArrayToMyRecord(ABuffer: TBytes): TRecordtype; class function ByteArrayToMyRecord(ABuffer: TBytes): TRecordtype; static; end; // geht TGenericTRecord = class function ByteArrayToMyRecord<TRecordtype>(ABuffer: TBytes): TRecordtype; class function ByteArrayToMyRecord<TRecordtype>(ABuffer: TBytes): TRecordtype; static; end; // geht nicht function ByteArrayToMyRecord<TRecordtype>(ABuffer: TBytes): TRecordtype; |
AW: Generic record
Zitat:
|
AW: Generic record
schau mal hier rein vllt bringt dich das weiter
![]() |
AW: Generic record
@himitsu :
warum benötige ich Zitat:
Delphi-Quellcode:
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; type TMyRecordA = record Details: string[255]; FileName: string[255]; FileDate: TDateTime; FileSize: Integer; Recordsize: Integer; end; TMyRecordB = record Details: string[255]; x: Real; y: Real; z: Real; end; TMyRecordC = record FileDate: TDateTime; FileSize: Integer; x: Real; y: Real; z: Real; end; TGenericRecord<TRecordType> = class value : TRecordType ; /// <summary> /// Convert Byte to Record , outputtype : TRecordType /// </summary> /// <param name="ABuffer"> /// Byte Array /// </param> function ByteArrayToMyRecord(ABuffer: TBytes): TRecordType; // class function ByteArrayToMyRecord(ABuffer: TBytes): TRecordType; static; /// <summary> /// Store a Record into a BYTE Array /// </summary> /// <param name="aRecord"> /// adjust this record definition to your needs /// </param> function MyRecordToByteArray(aRecord: TRecordType): TBytes; // class function MyRecordToByteArray(aRecord: TRecordType): TBytes; static; end; var Form1: TForm1; implementation {$R *.dfm} function TGenericRecord<TRecordType>.MyRecordToByteArray(aRecord: TRecordType): TBytes; var LSource: PAnsiChar; begin LSource := PAnsiChar(@aRecord); SetLength(Result, SizeOf(TRecordType)); Move(LSource[0], Result[0], SizeOf(TRecordType)); end; function TGenericRecord<TRecordType>.ByteArrayToMyRecord(ABuffer: TBytes): TRecordType; var LDest: PAnsiChar; begin LDest := PAnsiChar(@Result); Move(ABuffer[0], LDest[0], SizeOf(TRecordType)); end ; procedure TForm1.Button1Click(Sender: TObject); var a_record : TGenericRecord<TMyRecordA>; b_record : TGenericRecord<TMyRecordB>; c_record : TGenericRecord<TMyRecordC>; ABuffer : TBytes; begin /// create class a_record :=TGenericRecord<TMyRecordA>.Create; b_record :=TGenericRecord<TMyRecordB>.Create; c_record :=TGenericRecord<TMyRecordC>.Create; /// einb paar werte zuweisen ..... a_record.value.Details := '#1 bla bla'; a_record.value.FileName := '#2 bla bla'; a_record.value.Recordsize := 100; a_record.value.FileSize := 222; b_record.value.x := 1; b_record.value.y := 2; b_record.value.z := 3; /// im buffer daten zwischenlagern ABuffer := a_record.MyRecordToByteArray(a_record.value); /// löschen oder mit anderen daten arbeiten a_record.value.Details := '.....'; a_record.value.FileName := '----'; a_record.value.Recordsize := -1; a_record.value.FileSize := -2; // Daten wieder aus dem Buffer zurücklesen a_record.value := a_record.ByteArrayToMyRecord(ABuffer); /// alte daten sind wieder da :-) memo1.lines.add( a_record.value.Details) ; memo1.lines.add( a_record.value.Filename) ; /// free class a_record.Free; b_record.Free; c_record.Free; end; end |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:07 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