program AutoMappingObjects; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Generics.Collections, Quick.Commons, Quick.Console, Quick.JSONRecord, Quick.Json.Serializer, Quick.AutoMapper; type TJob = record Name : string; DateFrom : TDateTime; DateTo : TDateTime; end; TCarType = (ctOil, ctDiesel); TAgentStatus = (stActive, stIdle, stFail); TCar = class private fModel : string; fCarType : TCarType; published property Model : string read fModel write fModel; property CarType : TCarType read fCarType write fCarType; end; TCarList = TObjectList; TAgent = record Name : string; Status : TAgentStatus; end; TAgentList = TList; TUserBase = class(TJsonRecord) private fName : string; fAge : Integer; fCreationDate : TDateTime; fNumbers : TArray; fAgent : TAgent; published property Name : string read fName write fName; property Age : Integer read fAge write fAge; property CreationDate : TDateTime read fCreationDate write fCreationDate; property Numbers : TArray read fNumbers write fNumbers; property Agent : TAgent read fAgent write fAgent; end; TPointsList = TList; TUser = class(TUserBase) private fId : Int64; fCash : Integer; fJob : TJob; fCar : TCar; fCarList : TCarList; fPoints : TPointsList; fAgentList : TAgentList; fTags : TArray; public constructor Create; destructor Destroy; override; published property Id : Int64 read fId write fId; property Cash : Integer read fCash write fCash; property Job : TJob read fJob write fJob; property Car : TCar read fCar write fCar; property CarList : TCarList read fCarList write fCarList; property Points : TPointsList read fPoints write fPoints; property AgentList : TAgentList read fAgentList write fAgentList; property Tags : TArray read fTags write fTags; end; TUser2 = class(TUserBase) private fIdUser : Int64; fJob : TJob; fMoney : Integer; fCar : TCar; fCarList : TCarList; fPoints : TPointsList; fAgentList : TAgentList; fJobName : string; public constructor Create; destructor Destroy; override; published property IdUser : Int64 read fIdUser write fIdUser; property Money : Integer read fMoney write fMoney; property Job : TJob read fJob write fJob; property Car : TCar read fCar write fCar; property CarList : TCarList read fCarList write fCarList; property Points : TPointsList read fPoints write fPoints; property AgentList : TAgentList read fAgentList write fAgentList; property JobName : string read fJobName write fJobName; end; var User : TUser; User2 : TUser2; User3 : TUser2; job : TJob; AutoMapper : TAutoMapper; {$IFNDEF FPC} InterfacedAutoMapper : IAutoMapper; {$ENDIF} { TUser } constructor TUser.Create; begin fCar := TCar.Create; fCarList := TCarList.Create(True); fPoints := TPointsList.Create; fAgentList := TAgentList.Create; fTags := []; end; destructor TUser.Destroy; begin fCar.Free; fCarList.Free; fPoints.Free; fAgentList.Free; inherited; end; { TUser2 } constructor TUser2.Create; begin fCar := TCar.Create; fCarList := TCarList.Create(True); fPoints := TPointsList.Create; fAgentList := TAgentList.Create; end; destructor TUser2.Destroy; begin fCar.Free; fCarList.Free; fPoints.Free; fAgentList.Free; inherited; end; var car : TCar; agent : TAgent; begin ReportMemoryLeaksOnShutdown := True; try User := TUser.Create; User.Id := 17; User.CreationDate := Now(); User.Name := 'John Miller'; User.Age := 30; User.Numbers := [1,2,3,4,5]; User.Cash := 3500; job.Name := 'Designer'; job.DateFrom := IncMonth(Now(),-12); job.DateTo := Now(); User.Job := job; User.Car.Model := 'Ferrari'; User.Car.CarType := ctOil; car := TCar.Create; car.Model := 'Ford'; car.CarType := ctDiesel; User.CarList.Add(car); car := TCar.Create; car.Model := 'Nissan'; car.CarType := ctDiesel; User.CarList.Add(car); User.Points.Add(77); User.Points.Add(100); User.Points.Add(30); agent.Name := 'FirstAgent'; agent.Status := TAgentStatus.stIdle; User.Agent := agent; User.AgentList.Add(agent); agent.Name := 'SecondAgent'; agent.Status := TAgentStatus.stFail; User.AgentList.Add(agent); User.Tags := ['Tag1','Tag2','Tag3']; //User2 := TMapper.Map(User); AutoMapper := TAutoMapper.Create; try //option1: you can define auto map different named properties (if OnDoMapping assigned customaping will be no effect) AutoMapper.CustomMapping.AddMap('Cash','Money'); AutoMapper.CustomMapping.AddMap('Id','IdUser'); AutoMapper.CustomMapping.AddMap('Job.Name','JobName'); //option2: you can decide to modify each property manually or allow to auto someones AutoMapper.OnDoMapping := procedure(const aSrcObj : TUser; const aTargetName : string; out Value : TFlexValue) begin if aTargetName = 'Money' then Value := aSrcObj.Cash * 2 else if aTargetName = 'IdUser' then Value := aSrcObj.Id; end; //option3: you can modify some properties after automapping done AutoMapper.OnAfterMapping := procedure(const aSrcObj : TUser; aTgtObj : TUser2) begin aTgtObj.Money := aSrcObj.Cash * 2; aTgtObj.IdUser := aSrcObj.Id; end; User2 := AutoMapper.Map(User); //User2 := TUser2.Create; //User.MapTo(User2); //User2.MapFrom(User); //User2 := User.Map; //UserClone := User.Clone as TUser; //User2 := TUser2(User.Clone); //User2 := TMapper.Clone(User) as TUser2; {$IFNDEF FPC} InterfacedAutoMapper := TAutoMapper.Create; InterfacedAutoMapper.SetOnDoMapping( procedure(const aSrcObj : TUser; const aTargetName : string; out Value : TFlexValue) begin if aTargetName = 'Money' then Value := aSrcObj.Cash * 2 else if aTargetName = 'IdUser' then Value := aSrcObj.Id; end ); InterfacedAutoMapper.SetOnAfterMapping( procedure(const aSrcObj : TUser; aTgtObj : TUser2) begin aTgtObj.Money := aSrcObj.Cash * 2; aTgtObj.IdUser := aSrcObj.Id; end ); user3 := InterfacedAutoMapper.Map(User); {$ENDIF} cout('COMPARE Instanced Mapper USER VS USER2',etTrace); cout('User.Id = %d / User2.IdUser = %d',[User.Id,User2.IdUser],etInfo); cout('User.CreationDate = %s / User2.CreationDate = %s',[DateTimeToStr(User.CreationDate),DateTimetoStr(User2.CreationDate)],etInfo); cout('User.Name = %s / User2.Name = %s',[User.Name,User2.Name],etInfo); cout('User.Age = %d / User2.Age = %d',[User.Age,User2.Age],etInfo); cout('User.Numbers = %d / User2.Numbers = %d',[User.Numbers[1],User2.Numbers[1]],etInfo); cout('User.Cash = %d / User2.Money = %d',[User.Cash,User2.Money],etInfo); cout('User.Job.Name = %s / User2.Job.Name = %s',[User.Job.Name,User2.Job.Name],etInfo); cout('User.Job.DateFrom = %s / User2.Job.DateFrom = %s',[DateTimeToStr(User.Job.DateFrom),DateTimeToStr(User2.Job.DateFrom)],etInfo); cout('User.Car.Model = %s / User2.Car.Model = %s',[User.Car.Model,User2.Car.Model],etInfo); {$IFNDEF FPC} cout('COMPARE Interfaced Mapper USER VS USER3',etTrace); cout('User.Id = %d / User3.IdUser = %d',[User.Id,User3.IdUser],etInfo); cout('User.CreationDate = %s / User3.CreationDate = %s',[DateTimeToStr(User.CreationDate),DateTimetoStr(User3.CreationDate)],etInfo); cout('User.Name = %s / User3.Name = %s',[User.Name,User3.Name],etInfo); cout('User.Age = %d / User3.Age = %d',[User.Age,User3.Age],etInfo); cout('User.Numbers = %d / User3.Numbers = %d',[User.Numbers[1],User3.Numbers[1]],etInfo); cout('User.Cash = %d / User3.Money = %d',[User.Cash,User3.Money],etInfo); cout('User.Job.Name = %s / User3.Job.Name = %s',[User.Job.Name,User3.Job.Name],etInfo); cout('User.Job.DateFrom = %s / User3.Job.DateFrom = %s',[DateTimeToStr(User.Job.DateFrom),DateTimeToStr(User3.Job.DateFrom)],etInfo); cout('User.Car.Model = %s / User3.Car.Model = %s',[User.Car.Model,User3.Car.Model],etInfo); {$ENDIF} cout(' ',etInfo); cout('USER AS JSON RESULT',etTrace); cout('%s',[User.ToJson],etInfo); cout(' ',etInfo); user.Free; cout('USER2 AS JSON RESULT',etTrace); cout('%s',[User2.ToJson],etInfo); {$IFNDEF FPC} cout(' ',etInfo); cout('USER3 AS JSON RESULT',etTrace); cout('%s',[User3.ToJson],etInfo); {$ENDIF} finally AutoMapper.Free; User2.Free; User3.Free; end; ConsoleWaitForEnterKey; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.