AGB  ·  Datenschutz  ·  Impressum  







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

Generic record

Ein Thema von bernhard_LA · begonnen am 5. Mär 2012 · letzter Beitrag vom 5. Mär 2012
Antwort Antwort
Seite 1 von 2  1 2      
bernhard_LA

Registriert seit: 8. Jun 2009
Ort: Bayern
1.138 Beiträge
 
Delphi 11 Alexandria
 
#1

Generic record

  Alt 5. Mär 2012, 11:42
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;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

AW: Generic record

  Alt 5. Mär 2012, 11:49
Dein genric Record ist eine generic Class

TGenericRecord<x> entspricht nicht TGenericRecord

function MyRecordToByteArray<X>(aRecord: TGenericRecord<x>): TBytes; , da aber keine generischen Prozeduren möglich sind, muß dieses eine Methode eines Records oder eines Objekts werden.

statt
Zitat:
SizeOf(TGenericRecord)
muß es dann statt
Zitat:
SizeOf(TGenericRecord<X>)
werden, oder einfach nur statt
Zitat:
SizeOf(aRecord)
.
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.027 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#3

AW: Generic record

  Alt 5. Mär 2012, 12:06
Ich glaub, du möchtest so etwas:

Delphi-Quellcode:
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;
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.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
bernhard_LA

Registriert seit: 8. Jun 2009
Ort: Bayern
1.138 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Generic record

  Alt 5. Mär 2012, 12:38
@ 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 ;



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;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

AW: Generic record

  Alt 5. Mär 2012, 13:00
Zurückgeben kann man es, aber function MyFunction<T>(...): ...; ist nicht möglich ... das geht leider nur bei Methoden (Record oder Object).
$2B or not $2B
  Mit Zitat antworten Zitat
bernhard_LA

Registriert seit: 8. Jun 2009
Ort: Bayern
1.138 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Generic record

  Alt 5. Mär 2012, 13:11
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:

procedure (a : Integer; var TGenericRecordType<T> );
codieren.


bzw.
Zitat:
da aber keine generischen Prozeduren möglich sind, muß dieses eine Methode eines Records oder eines Objekts werden


TGenericTRecord <TRecordtype>= class

function ByteArrayToMyRecord(ABuffer: TBytes): TRecordtype
end;

Geändert von bernhard_LA ( 5. Mär 2012 um 13:18 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

AW: Generic record

  Alt 5. Mär 2012, 13:23
Natürlich nicht.
Beim Überladen muß sich die Aufrufsignatur unterscheifen, also die Parameter müssen unterschiedlich sein.
Bei dir sind sie aber gleich.

Zitat:
da aber keine generischen Prozeduren möglich sind, muß dieses eine Methode eines Records oder eines Objekts werden
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;
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.027 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#8

AW: Generic record

  Alt 5. Mär 2012, 13:44
@ Stevie : in meinen records können leider auch Strings vorkommen .... kann damit Deine Lösung nicht verwenden
Ja, genau wie alle anderen Ansätze in diesem Thread, die auf SizeOf, Move und ähnlichem basieren
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Pitschki1801

Registriert seit: 9. Feb 2012
14 Beiträge
 
Delphi XE Professional
 
#9

AW: Generic record

  Alt 5. Mär 2012, 14:44
schau mal hier rein vllt bringt dich das weiter Tut-Generics
  Mit Zitat antworten Zitat
bernhard_LA

Registriert seit: 8. Jun 2009
Ort: Bayern
1.138 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Generic record

  Alt 5. Mär 2012, 14:52
@himitsu :

warum benötige ich
Zitat:
class function ByteArrayToMyRecord(ABuffer: TBytes): TRecordType; static;
anbei meine aktuelle Lösung, scheint zu spielen ... im simplen Quick&Dirty - Test







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

Geändert von bernhard_LA ( 5. Mär 2012 um 15:04 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 00:37 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