Delphi Can
Record Üzerindeki Verilere Dinamik Erişim - Baskı Önizleme

+- Delphi Can (http://www.delphican.com)
+-- Forum: Eğitim (http://www.delphican.com/forumdisplay.php?fid=19)
+--- Forum: Makale (http://www.delphican.com/forumdisplay.php?fid=20)
+--- Konu Başlığı: Record Üzerindeki Verilere Dinamik Erişim (/showthread.php?tid=3545)



Record Üzerindeki Verilere Dinamik Erişim - narkotik - 13-04-2019

Merhaba,

Projem gereği her yerde kullanabileceğim bir record yapısı kuruyorum. Bu nedenle recordlar üzerinde dinamik işlemler yapmam gerekiyor. 
Başkalarınında işine yarayacağını düşünerek http://www.delphican.com/showthread.php?tid=1433 konusuna ithafen, record üzerindeki verilere erişim ve value gönderme üzerine örnek kod ve proje aşağıdadır.

ADjok7.png

Örnek Proje Kodlar

unit RecordLib;
{****************************
 RecordLib.pas 2019
 S.B
*****************************}
interface

 uses Rtti,TypInfo;

 type
   TFieldInform = record
   FieldName  : String;
   FieldType  : String;
   FieldValue : Variant;
 end;

 type
   TRecordInfo<RecordClass:record> = class
 public
   class function  GetFieldList(const ARecord:RecordClass): TArray<TFieldInform>;
   class procedure SetFieldValue(var ARecord:RecordClass;const AFieldName:String;const AValue:Variant);
 end;

implementation

{ TRecordInfo<RecordClass> }

class function TRecordInfo<RecordClass>.GetFieldList(const ARecord: RecordClass): TArray<TFieldInform>;
var
 xContext : TRttiContext;
 xType    : TRttiType;
 xField   : TRttiField;
 xCounter : Integer;
begin
 xContext := TRttiContext.Create;
 try
   SetLength(Result,Length(xContext.GetType(TypeInfo(RecordClass)).GetFields));
   xCounter := 0;
   for xField in xContext.GetType(TypeInfo(RecordClass)).GetFields do
   begin
     xType                       := xField.FieldType;
     Result[xCounter].FieldName  := xField.Name;
     Result[xCounter].FieldType  := xField.FieldType.Name;
     Result[xCounter].FieldValue := xField.GetValue(@ARecord).AsVariant;
     xCounter                    := Succ(xCounter);
   end;
 finally
   xContext.Free;
 end;
end;

class procedure TRecordInfo<RecordClass>.SetFieldValue(var ARecord:RecordClass;const AFieldName:String;const AValue:Variant);
var
 xContext : TRttiContext;
 xType    : TRttiType;
 xField   : TRttiField;
 xValue   : TValue;
begin
 xContext := TRttiContext.Create;
 try
   for xField in xContext.GetType(TypeInfo(RecordClass)).GetFields do
   begin
     xType := xField.FieldType;
     if xField.Name = AFieldName then
     begin
       case PTypeInfo(xType.Handle).Kind of
         tkInteger :
           begin
             xValue := TValue.From<Integer>(AValue);
             xField.SetValue(@ARecord,xValue);
           end;
         tkUString :
           begin
             xValue := TValue.From<String>(AValue);
             xField.SetValue(@ARecord,xValue);
           end;
         tkFloat :
           begin
             xValue := TValue.From<Double>(AValue);
             xField.SetValue(@ARecord,xValue);
           end;
       end;
     end;
   end;
 finally
   xContext.Free;
 end;
end;

end.

Örnek

  type
   TTestRecord = record
   VAL_STR : String;
   VAL_INT : Integer;
   VAL_DTE : TDateTime;
   VAL_FLT : Double;
 end;

procedure TFrmTestRecord.BtnOKClick(Sender: TObject);
Var
 xTestRecord : TTestRecord;
 xFieldArray : TArray<TFieldInform>;
 Ind         : Integer;
begin
 memDefault.Clear;
 memNew.Clear;

 xTestRecord.VAL_STR := 'Test1';
 xTestRecord.VAL_INT := 1;
 xTestRecord.VAL_DTE := StrToDateTime('01.01.2019 01:10:15');
 xTestRecord.VAL_FLT := 0.1;

 xFieldArray := TRecordInfo<TTestRecord>.GetFieldList(xTestRecord);
 for Ind := Low(xFieldArray) to High(xFieldArray) do
     memDefault.Lines.Add
     (
       Format('FieldName[%s] -- FieldType[%s] -- Value=%s',
       [
         xFieldArray[Ind].FieldName
         ,xFieldArray[Ind].FieldType
         ,VarToStr(xFieldArray[Ind].FieldValue)
       ]
       )
     );

 TRecordInfo<TTestRecord>.SetFieldValue(xTestRecord,'VAL_STR','Test2');
 TRecordInfo<TTestRecord>.SetFieldValue(xTestRecord,'VAL_INT',2);
 TRecordInfo<TTestRecord>.SetFieldValue(xTestRecord,'VAL_DTE',Now);
 TRecordInfo<TTestRecord>.SetFieldValue(xTestRecord,'VAL_FLT',0.2);

 xFieldArray := TRecordInfo<TTestRecord>.GetFieldList(xTestRecord);
 for Ind := Low(xFieldArray) to High(xFieldArray) do
     memNew.Lines.Add
     (
       Format('FieldName[%s] -- FieldType[%s] -- Value=%s',
       [
         xFieldArray[Ind].FieldName
         ,xFieldArray[Ind].FieldType
         ,VarToStr(xFieldArray[Ind].FieldValue)
       ]
       )
     );
end;