Newsgroup: it.comp.lang.delphi
Titolo: identificare i campi di un record tramite stringhe

In un programma, definisco un record con i relativi campi come segue:
type TMyRecord = record
       campo1: string;
       campo2: integer;
       campo3: string;
       ......
      campoX:string;
 end;
e una variabile ti tipo TMyRecord
 var T : TMyRecord
sapete dirmi se esiste un meotdo o un trucco per ottenere, dalla
variabile T di tipo TMYrecord, il valore di uno dei campi passando
questo come stringa ?
Oppure scorrere con un ciclo tutti i campi di T, senza sapere a priori
quali essi siano e come si chiamino, per leggerne i valori ?
Grazie anticipatamente
Saluti
Andrea
----------------------------------------------
<< Dubito, quindi potrei essere >>
-----------------------------------------------

 -----------------------------------------------
<<Potrei dubitare, quindi esisto >>
:)
Ciao.
Mimmo.

IL problema sta nell'accesso ai dati dell'oggetto record:
se ho un record anche semplice, tipo
type Trecord = record
        cognome : string;
        nome         : string;
       professione : string;
 end;
(ma è solo l'esempio: nel mio caso i campi sono una ventina)
e devo creare la possibilità a run-time di accedere ad uno qualasiasi
dei campi per leggere il valore in esso contenuto, senza sapere in
fase i scrittura quale sarà il campo a cui accedere, come posso fare ?
Mi spiego meglio: se i campi fossero campo0, campo1, campo2, campo3
posso scrivere un ciclo
 for x = 0 to 3 do
    variabilestringa =   Trecord."campox"  ?
oppure come posso fare ? Potreste fornirmi un esempio ?
Grazie ancora
Saluti
Andrea


     variabilestringa =   Trecord."campox"  ?
Non penso proprio sia possibile fare quello che chiedi tu.
La definizione dei record deve essere chiara in fase di sviluppo e non può
essere "ritoccata" a runtime.
Potresti usare i database, eventualmente... la gestione dei campi è
"dinamica" anche se questo può portare a tirarti dietro tutta la parte DB ed
eventualmente BDE per alcuni database.
Se il problema  è che certi campi devono essere personalizzati e aggiunti in
fase di esecuzione, la soluzione del database è più corretta.
Oppure come ti hanno già suggerito puoi usare Tstringlist o gli array
dinamici.
con i Tstrignlist potresti implementare una soluzione tipo
valori items:
...
Proprietà1|valore <- |=Pipe o qualunque altro carattere che non può
comparire nè in valore nè in proprietà
Proprietà2|valore
Proprietà3|valore
Proprietà4|valore
...
e se te la cavi bene potresti fare un componente figlio di Tstringlist che
gestisca in automatico la ricerca/aggiunta/sostituzione dei tuoi valori, ma
che internamente utilizzi lo stesso principio di "Proprietà|Valore"
Magari come complessità iniziale può essere maggiore, ma non doversi gestire
la parte database può essere un motivo sufficiente. Ma dipende sempre da
"cosa" deve fare il tuo programma.
Ciao
Matteo

fase di esecuzione, la soluzione del database è più corretta.
Probabilmente mi sono spiegato male io: la definizione è intoccabile.
Volevo solo sapere se era possibile recuperare il valore di un campo
del record passando il nome del campo come stringa (parlando di DB, un
pò come usare il metodo fieldbyname("nomecampo").asstring), ma credo
non sia proprio possibile.
Alternativamente  avevo pensato di creare un oggetto che contenesse 2
TStrings: uno con i nomi di campo ed uno con i valori. Il recupero,
inserimento,aggiornamento dei dati passando il nome del campo
avverrebbe appunto cercando il valore nei nomi dei campi,
recuperandone l'indice e usandolo per leggere il valore dal secondo
elenco.
Speravo peròche esstesse una soluzione migliore
Grazie per l'interessamento


 non sia proprio possibile.
Credo che debba essere possibile.
Lasciando un attimo perdere i record, se crei una classe che wrappa il
tuo record, puoi sicuramente aggiungere un metodo ValueByName(const
NomeCampo: string): Variant che, supposto che esista il campo, ti torna
il valore (come Variant), altrimenti Null.
Saluti
Paolo Arosio

 
Prego.

 end;
Ciao.
Mimmo.

 non sia proprio possibile.
Ciao,
        la soluzione che ti propongo non è particolarmente
bella/efficiente/OO ma dovrebbe realizzare quello che chiedi...
type
  TMioRecord=record
    iValore: integer;
    sValore: string;
    dtTempo: TDateTime;
    sNome: string;
  end;
  PMioRecord = ^TMioRecord;
function Scrivi(mrRecord: PMioRecord; sCampo: string; vValue: Variant):
boolean;
begin
  result := True;
  if SameText(sCampo, 'iValore') then
    mrRecord^.iValore := vValue else
  if SameText(sCampo, 'sValore') then
    mrRecord^.sValore := vValue else
  if SameText(sCampo, 'dtTempo') then
    mrRecord^.dtTempo := vValue else
  if SameText(sCampo, 'sNome') then
    mrRecord^.sNome := vValue else
  result := False;
end;
function Leggi(mrRecord: PMioRecord; sCampo: string; var vValue: Variant):
boolean;
begin
  result := True;
  if SameText(sCampo, 'iValore') then
    vValue := mrRecord^.iValore else
  if SameText(sCampo, 'sValore') then
    vValue := mrRecord^.sValore else
  if SameText(sCampo, 'dtTempo') then
    vValue := mrRecord^.dtTempo else
  if SameText(sCampo, 'sNome') then
    vValue := mrRecord^.sNome else
  result := False;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  mrDati: TMioRecord;
  vLetto: Variant;
begin
  if Not Scrivi(@mrDati, 'iValore', 5) then
    raise Exception.Create('Errore in scrittura');
  if Not Leggi(@mrDati, 'iValore', vLetto) then
    raise Exception.Create('Errore in lettura')
  else
    ShowMessage(VarToStr(vLetto));
end;
Spero ti sia utile,
--
Andrea /\/\agni
e-mail: 
ama...@supereva.it