2
0
Эх сурвалжийг харах

AutoMapper TList and TObjectList

Unknown 6 жил өмнө
parent
commit
ba263843dd
1 өөрчлөгдсөн 123 нэмэгдсэн , 8 устгасан
  1. 123 8
      Quick.AutoMapper.pas

+ 123 - 8
Quick.AutoMapper.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.AutoMapper
   Description : Auto Mapper object properties
   Author      : Kike Pérez
-  Version     : 1.0
+  Version     : 1.1
   Created     : 25/08/2018
-  Modified    : 30/08/2018
+  Modified    : 23/09/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -36,9 +36,9 @@ interface
 uses
   SysUtils,
   Generics.Collections,
-  {$IFDEF FPC}
+  //{$IFDEF FPC}
   typinfo,
-  {$ENDIF}
+  //{$ENDIF}
   RTTI;
 
 type
@@ -58,6 +58,16 @@ type
     class procedure Map(aSrcObj : TObject; aTgtObj : TObject; aCustomMapping: TCustomMapping = nil);
   end;
 
+  TListMapper = class
+  public
+    class procedure Map(aSrcList, aTgtList: TObject; aCustomMapping: TCustomMapping);
+  end;
+
+  TObjListMapper = class
+  public
+    class procedure Map(aSrcObjList : TObject; aTgtObjList : TObject; aCustomMapping : TCustomMapping = nil);
+  end;
+
   TMapper<T : class, constructor> = class
   public
     class function Map(aSrcObj : TObject; aCustomMapping: TCustomMapping = nil): T; overload;
@@ -93,16 +103,19 @@ var
   tgtprop : TRttiProperty;
   mapname : string;
   obj : TObject;
+  clname : string;
 begin
-  if aTgtObj = nil then aTgtObj := aTgtObj.ClassType.Create;
+  if aTgtObj = nil then aTgtObj := GetTypeData(aTgtObj.ClassInfo).classType.Create;
 
+  rType := ctx.GetType(aSrcObj.ClassInfo);
   for tgtprop in ctx.GetType(aTgtObj.ClassInfo).GetProperties do
   begin
     if tgtprop.IsWritable then
     begin
+      if tgtprop.Name = 'Agent'
+        then Sleep(0);
       if not tgtprop.PropertyType.IsInstance then
       begin
-        rType := ctx.GetType(aSrcObj.ClassInfo);
         if Assigned(aCustomMapping) then
         begin
           if aCustomMapping.GetMap(tgtprop.Name,mapname) then
@@ -153,7 +166,10 @@ begin
         if obj <> nil then
         begin
           {$IFNDEF FPC}
-          TObjMapper.Map(rType.GetProperty(tgtprop.Name).GetValue(aSrcObj).AsObject,obj,aCustomMapping);
+          clname := rType.GetProperty(tgtprop.Name).GetValue(aSrcObj).AsObject.ClassName;
+          if clname.StartsWith('TObjectList') then TObjListMapper.Map(rType.GetProperty(tgtprop.Name).GetValue(aSrcObj).AsObject,obj,aCustomMapping)
+            else if clname.StartsWith('TList') then TListMapper.Map(rType.GetProperty(tgtprop.Name).GetValue(aSrcObj).AsObject,obj,aCustomMapping)
+              else TObjMapper.Map(rType.GetProperty(tgtprop.Name).GetValue(aSrcObj).AsObject,obj,aCustomMapping)
           {$ELSE}
           TObjMapper.Map(GetObjectProp(aSrcObj,tgtprop.Name),obj,aCustomMapping);
           SetObjectProp(aTgtObj,tgtprop.Name,obj);
@@ -192,7 +208,6 @@ begin
   inherited;
 end;
 
-{}
 function TAutoMapper<TClass1, TClass2>.Map(aSrcObj: TClass1): TClass2;
 begin
   Result := TMapper<TClass2>.Map(aSrcObj,fCustomMapping);
@@ -233,4 +248,104 @@ begin
   Result := fMapDictionary.TryGetValue(aName,vMapName);
 end;
 
+{ TListMapper }
+
+class procedure TListMapper.Map(aSrcList, aTgtList: TObject; aCustomMapping: TCustomMapping);
+{$IFNDEF FPC}
+var
+  rtype: TRttiType;
+  rtype2 : TRttiType;
+  typinfo : PTypeInfo;
+  methToArray: TRttiMethod;
+  value: TValue;
+  valuecop : TValue;
+  obj : TObject;
+  i : Integer;
+  rprop : TRttiProperty;
+  ctx : TRttiContext;
+begin
+  rtype := ctx.GetType(aSrcList.ClassInfo);
+  methToArray := rtype.GetMethod('ToArray');
+  if Assigned(methToArray) then
+  begin
+    value := methToArray.Invoke(aSrcList,[]);
+    Assert(value.IsArray);
+
+    rtype2 := ctx.GetType(aTgtList.ClassInfo);
+    rProp := rtype2.GetProperty('List');
+    typinfo := GetTypeData(rProp.PropertyType.Handle).DynArrElType^;
+
+    for i := 0 to value.GetArrayLength - 1 do
+    begin
+      if typinfo.Kind = tkClass then
+      begin
+        obj := typinfo.TypeData.ClassType.Create;
+        TObjMapper.Map(value.GetArrayElement(i).AsObject,obj,aCustomMapping);
+        TList<TObject>(aTgtList).Add(obj);
+      end
+      else if typinfo.Kind = tkRecord then
+      begin
+        valuecop := value.GetArrayElement(i);
+        //??
+      end
+      else
+      begin
+        valuecop := value.GetArrayElement(i);
+        case typinfo.Kind of
+          tkChar, tkString, tkWChar, tkWString : TList<string>(aTgtList).Add(valuecop.AsString);
+          tkInteger, tkInt64 : TList<Integer>(aTgtList).Add(valuecop.AsInt64);
+          tkFloat : TList<Extended>(aTgtList).Add(valuecop.AsExtended);
+        end;
+      end;
+    end;
+  end;
+end;
+{$ELSE}
+begin
+
+end;
+{$ENDIF}
+
+
+{ TObjListMapper }
+
+class procedure TObjListMapper.Map(aSrcObjList, aTgtObjList: TObject; aCustomMapping: TCustomMapping);
+{$IFNDEF FPC}
+var
+  rtype: TRttiType;
+  rtype2 : TRttiType;
+  typinfo : PTypeInfo;
+  methToArray: TRttiMethod;
+  value: TValue;
+  obj : TObject;
+  i : Integer;
+  rprop : TRttiProperty;
+  ctx : TRttiContext;
+begin
+  rtype := ctx.GetType(aSrcObjList.ClassInfo);
+  methToArray := rtype.GetMethod('ToArray');
+  if Assigned(methToArray) then
+  begin
+    value := methToArray.Invoke(aSrcObjList,[]);
+    Assert(value.IsArray);
+
+    rtype2 := ctx.GetType(aTgtObjList.ClassInfo);
+    rProp := rtype2.GetProperty('List');
+    typinfo := GetTypeData(rProp.PropertyType.Handle).DynArrElType^;
+
+    for i := 0 to value.GetArrayLength - 1 do
+    begin
+      obj := typinfo.TypeData.ClassType.Create;
+      TObjMapper.Map(value.GetArrayElement(i).AsObject,obj,aCustomMapping);
+      TObjectList<TObject>(aTgtObjList).Add(obj);
+    end;
+  end;
+end;
+{$ELSE}
+begin
+
+end;
+
+{$ENDIF}
+
 end.