QuickLib is a delphi/Firemonkey(Windows, Linux, Android, OSX & IOS) and fpc(Windows & Linux) library containing interesting and quick to implement functions, created to simplify application development and crossplatform support and improve productivity. Delphi XE8 – Delphi 12 Athens supported.
Give it a star
Please \”star\” this project in GitHub! It costs nothing but helps to reference the code.
Star History
Support
If you find this project useful, please consider making a donation.
Areas of functionality:
- Mapping: Map fields from a class to other class, copy objects, etc..
- Config: Use your config as an object and load/save from/to file (Json/Yaml) or Windows Registry.
- Serialization: Serialize objects to/from json/Yaml.
- Scheduling: Schedule tasks launching as independent threads with retry policies.
- Threading: Simplify run and control of multithread background tasks, Thread-safe Lists, queues, etc
- Data: Flexible data interchange and storage, allowing several input-output types.
- Cloud: Simplify cloud Azure/Amazon file management, send emails and more.
- Querying: Indexed Lists, Searchable Lists and Linq query system for generic lists and arrays.
- Benchmark: Time elapsed control and benchmark functions.
- Filesystem: Process and Services control, file modify monitors and helpers, etc…
- FailControl: Fail and Retry policies.
- Caching:: Cache string or objects to retrieve fast later.
- Templating: Simple string templating with dictionaries.
- Debuging: Utils to debug your code.
- Parameters: Work with commandline parameters.
Main units description:
- Quick.Commons: Functions frequently needed in the day to day of a developer.
- Quick.AppService: Allow a console app to run as console mode or service mode with same code simplifying debug tasks.
- Quick.Azure/Amazon: Simplifies blob iteraction with Azure and Amazon Cloud Storage.
- Quick.Network: CIDR and IP Range functions.
- Quick.Chrono: Chronometer and Benchmark a piece of code is simple.
- Quick.Console: Write log messages to console with colors and more…
- Quick.Log: Log to disk or memory with verbose levels and daily or max space rotation.
- Quick.Config: Load/Save a config as Json or Yaml file or Windows Registry keys and manage it as an object.
- Quick.FileMonitor: Monitorizes a file for changes and throws events.
- Quick.JsonUtils: Utils for working with json objects.
- Quick.SMTP: Send email with two code lines.
- Quick.Threads: Thread safe classes, scheduling and backgrounds tasks with retry policies.
- Quick.Process: Manages windows processes.
- Quick.Services: Manages windows services.
- Quick.Format: String format.
- Quick.RTTI.Utils: Simplifies working with RTTI.
- Quick.JsonSerializer: Serializes an object from/to json text. You can define if public or published will be processed (only Delphi, fpc rtti only supports published properties)
- Quick.AutoMapper: Map fields from one class to another class. Allows custom mappings to match different fields and custom mapping procedure to cast/convert fields manually.
- Quick.JsonRecord: Used as a DTO class, with json serialize and mapping functions included.
- Quick.Lists: Improved lists with indexing or search features.
- Quick.Value FlexValue stores any data type and allow pass to other class with integrated operators and autofrees.
- Quick.Arrays: Improved arrays.
- Quick.YAML: Yaml object structure.
- Quick.YAML.Serializer: Serialize/Deserialize object from/to Yaml.
- Quick.Expression: Evaluate object properties using expressions.
- Quick.Linq: Makes Linq queries to any TObjectList, TList, TArray and TXArray, performing Select by complex Where like SQL syntax, update and order over your list.
- Quick.MemoryCache: Caches objects/info with an expiration time, to avoid generate this info everytime is needed (database queries, hard to calculate info, etc).
- Quick.Collections: Collections improvements like IList and IObjectList with Linq inherited.
- Quick.Pooling: Creation of object pool to avoid external resource consum exhausts and overheads.
- Quick.Template: String template replacing with dictionary or delegate.
- Quick.Debug.Utils: Simple debugging and code benchmark utils.
- Quick.Parameters: Work with commandline parameters like a class.
- Quick.Url.Utils: Simple url manipulation
- Quick.RegEx.Utils: Commonly used RegEx comparison (email verification, password complexity, etc)
- Quick.Conditions: Pre and postcondition validations in fluent style.
Updates:
- NEW: RAD Studio 12 supported
- NEW: RAD Studio 11 supported
- NEW: Condition checks
- NEW: Commonly used RegEx validations
- NEW: Url manipulation utils
- NEW: QuickParameters to work with commandline arguments like a class.
- NEW: HttpServer custom and dynamic error pages.
- NEW: Debug utils
- NEW: String Template
- NEW: RAD Studio 10.4 supported
- NEW: Collections: IList and IObjectList with linQ support.
- NEW: Pooling: ObjectPool.
- NEW: Options file settings with sections.
- NEW: MemoryCache with expiration & object compression.
- NEW: Now included on RAD Studio GetIt package manager.
- NEW: Background & Scheduled task with retry policies
- NEW: RunTask, FaultControl
- NEW: Linq over generic lists and arrays.
- NEW: QuickConfig YAML provider.
- NEW: YAML Object and Serializer
- NEW: AutoMapper customapping path namespaces style.
- NEW: FlexArray, FlexPair & FlexPairArray.
- NEW: AutoMapper mapping procedures (see documentation below)
- NEW: JsonSerializer improved
- NEW: TXArray: array like TList
- NEW: Delphi Linux compatibility
- NEW: QuickConfigJson reload if config file changed
- NEW: First version with OSX/IOS partial support
- NEW: Delphinus-Support
Installation:
- From package managers:
- Search \”QuickLib\” on Delphinus or GetIt package managers and click Install
- From Github:
- Clone Github repository or download zip file and extract it.
- Add QuickLib folder to your path libraries on Delphi IDE.
Documentation:
Quick.AppService:
Allow a console app to run as console mode or service mode with same code simplifying debug tasks.
if not AppService.IsRunningAsService then begin ...your code running as console end else begin AppService.ServiceName := \'MyService\'; AppService.DisplayName := \'MyServicesvc\'; //you can pass an anonymous method to events AppService.OnStart := procedure begin ...your start code end; AppService.OnExecute := YourExecuteFunction; AppService.OnStop := YourStopFunction; AppService.CheckParams; end;
Quick.Azure/Amazon:
Simplifies blob iteraction with Azure and Amazon Cloud Storage.
//connect to a Azure blobstorage QuickAzure := TQuickAzure.Create(AzureAccountName,AzureAccountKey); //download a blob file to a stream done := QuickAzure.GetBlob(\'MyContainer\',\'MyFile.jpg\',ResponseInfo,MyStream); //check if exists a folder found := ExistFolder(\'MyContainer\',\'/Public/Documents/Personal\'); //list blobs starting with a pattern (recursively or not) for azBlob in ListBlobs(\'MyContainer\',\'/Public/Documents\',Recursive,ResponseInfo) do begin if azBlob.Size > 1000 then Showmessage(azBlob.Name); end;
Quick.Network:
CIDR and IP Range functions.
//convert ip string to integer IPv4ToInt(\'192.168.1.10\'); //get first and last ip of a subnet scope GetIpRange(\'192.168.100.0\',\'255.255.255.0\',LowIp,HighIP);
Quick.Commons:
Functions frequently needed in the everyday of a developer.
//coverts UTC time TDateTime to Local date time UTCToLocalTime(MyUTCTime); //generate a 10 char length random password with alfanumeric and signs. RandomPassword(10,[pfIncludeNumbers,pfIncludeSigns]); //Capitalize every word of a phrase CapitalizeAll(\'the grey fox\'); //returns \"The Grey Fox\" //Simple TCounter and TTimeCounter for loops counter := TCounter; counter.Init(200); timecounter : TTimeCounter; timecounter.Init(10000); while true do begin Inc(n); {your procedural process here} //every 200 steps writes to console if counter.Check then writeln(Format(\'Processed %d entries\',[n])); //every 10 seconds writes to console if timecounter.Check then writeln(\'Im working...\'); end;
Quick.Chrono:
Chronometer and Benchmark a piece of code is simple.
//get elapsed time execution of a code part Chrono := TChronometer.Create(False); Chrono.Start; ...code you need benchmark Chrono.Stop; //shows elapsed time in LongTime format (2 hour(s) and 10 minute(s)) Showmessage(Chrono.TimeElapsed(True)); //shows elapsed time in ShortTime format (02:10:00) Showmessage(Chrono.TimeElapsed(False)); //get benchmak info of a process Chrono := TChronoBenchMark.Create; Chrono.TotalProcess := 100000; for i := 1 to 10000 do begin {your process here} Chrono.CurrentProcess := i; //shows estimated time your process will take in x hour(s), x minute(s) x second(s) format writeln(Chrono.EstimatedTime(True)); //shows speed: num items per second processed of your process writeln(Format(\'Items processed %d/sec\',[Chrono.Speed])); end; writeln(Chrono.ElapsedTime(False)); //shows total time elapsed in 00:00:00 format
Quick.Console:
Write log messages to console with colors and more…
//define which level of output needed Console.Verbose := LOG_DEBUG; //writes line to console in red color cout(\'Error x\',etError); //writes formatted line in green color coutFmt(\'Proccess %s finished\',[ProccesName],etSuccess); //writes integer cout(12348); //Connect a QuickLog and write to disk and screen with one line of code (with independent verbose levels) MyQuickLog := TQuickLog.Create; MyQuickLog.Verbose := LOG_ALL; Console.Verbose := LOG_ONLYERRORS; Console.Log := MyQuickLog;
Quick.Log:
Log to disk or memory with verbose levels and daily or max space rotation.
//write a header on start with info as running path, appname, debugmode, user, etc... Log.ShowHeader := True; //sets log with rotation at 20MB Log.SetLog(\'.\\mylog.log\',False,20); //write an error message Log.Add(\'Error x\',etError); //write formatted error message Log.Add(\'Error is %s\',[ErrorStr],etError);
Quick.Config:
Load/Save a config as Json or Yaml file or Windows Registry keys. Create a descend class from TAppConfigJson, TAppConfigYaml or TAppConfigRegistry and added published properties will be loaded/saved. Files configs can be reloaded on detect files changes.
//create a class heritage TMyConfig = class(TAppConfigJson) private fName : string; fSurname : string; fStatus : Integer; published property Name : string read fName write fName; property SurName : string read fSurname write fSurname; property Status : Integer read fStatus write fStatus; end; //create your config to json file //Add Quick.Config.Json to your uses MyConfig := TMyConfig.Create(\'Config.json\'); MyConfig.Provider.CreateIfNotExists := True; MyConfig.Provider.ReloadIfFileModified := True; MyConfig.Name := \'John\'; MyConfig.Surname := \'Smith\'; //load MyConfig.Load; //save MyConfig.Save; //create your config to Windows Registry //Add Quick.Config.Registry to your uses MyConfig := TMyConfig.Create; //Define Registry as HKEY_CURRENT_USER\\Software\\MyApp MyConfig.HRoot := HKEY_CURRENT_USER; MyConfig.MainKey := \'MyApp\'; MyConfig.Name := \'John\'; MyConfig.Surname := \'Smith\'; //load MyConfig.Load; //save MyConfig.Save; //Create a custom Config with no default provider TMyConfig = class(TAppConfig) ...your properties end; MyConfig := TMyConfig.Create(TAppConfigJsonProvider.Create(\'.\\config.json\');
Quick.FileMonitor:
Monitorizes a file for changes and throws events.
FileMonitor.Filename := \'.\\myfile.txt\'; //check file changes every 2 seconds FileMonitor.Interval := 2000; //watch for deleted or modified file events FileMonitor.Notifies := [mnFileModified, mnFileDeleted)]; FileMonitor.OnFileChange := MyFileChangeFunction; FileMonitor.Enabled := True;
Quick.JsonUtils:
Utils for working with json objects.
//When unit declared in uses, a TObject Helper allows all your objects to be loaded or saved to/from json string MyObject.FromJson := jsonstring; MyString := MyObject.ToJson; //You can clone simple objects with clone function MyObject1.Clone(MyObject2);
Quick.SMTP:
Send email with two code lines.
//Send email SMTP := TSMTP.Create(\'mail.domain.com\',25,False); SMTP.SendMail(\'my@email.com\',\'to@email.com\',\'Email subject\',\'My message body\'); //You can define more advanced options SMTP.SenderName := \'John\'; SMTP.From := \'my@email.com\'; SMTP.Recipient := \'one@email.com,two@email.com\'; SMTP.Subject := \'Email subject\'; SMTP.AddBodyFromFile := \'.\\body.html\'; SMTP.CC := \'other@email.com\'; SMTP.BCC := \'more@email.com\'; SMTP.Attachments.Add(\'.\\notes.txt\'); SMTP.SendMail;
Quick.Threads:
Thread safe classes.
TThreadedQueueCS: Version of TThreadedQueue with Critical Section.
TThreadObjectList: Thread safe Object List.
TThreadedQueueList: Thread safe Queue List. Autogrow and with Critical Section.
TAnonymousThread: Creates anonymous thread defining unchained Execute and OnTerminate methods. Use Execute_Sync and OnTerminate_Sync methods if code needs to update UI.
- Execute: Specify code to execute on start.
- Execute_Sync: Like Execute but runs code with syncronized thread method (avoids problems if your code updates UI).
- OnTerminate: Specify code to execute when task finishes.
- OnTerminate_Sync: Like OnTerminate but runs code with syncronized thread method (avoids problems if your code updates UI).
- Start: Starts thread execution.
//simple anonymousthread TAnonymousThread.Execute( procedure var i : Integer; begin for i := 0 to 10 do cout(\'Working %d\',[i],etTrace); cout(\'executed thread\',etSuccess); end) .OnTerminate( procedure begin cout(\'terminated thread\',etSuccess); cout(\'PRESS <ENTER> TO EXIT\',etInfo); end) .Start;
TRunTask: Launch an autofree single task thread with fault & retry control policies. Params can be passed and created into code.
-
Define code to execute:
- Execute: Specify Task name, parameters to pass to anonymous method(If OwnedParams=true, task will free params on termination task) and method than will be executed.
- Execute_Sync: Like Execute but runs code with synchronize thread method (avoids problems if your code updates UI).
- SetParameter: Defines values or objects needed by your task.
-
Define events to control:
- OnInitialize: Specify code to run before main execute task (this code only runs one time, OnExecute can be retried more than one time)
- OnRetry: Specify code to run when execution fails and decide if needs to retry or cancel next retries.
- OnTerminate: Specify code to execute when task finishes.
- OnTerminate_Sync: Like OnTerminate but runs code with syncronized thread method (avoids problems if your code updates UI).
- OnException: Specify code to execute when task generates an exception.
-
Define fail/retry policies:
- RetryForever: If execution fails, code will be retry forever until task executes ok.
- Retry: If execution fails, code will be retry x times.
- WaitAndRetry: If execution fails, code will be retry x times, and wait x millisecons before each retry. You can specify number of retries and wait time between retries.
- Run: Starts task execution.
TRunTask.Execute(
procedure(task : ITask)
var
stream : TStringStream;
response : IHttpRequestResponse;
begin
stream := TStringStream.Create;
try
response := TJsonHttpClient(task[\'httpclient\'].AsObject).Get(task[\'url\']);
task.Result := response.StatusCode;
if response.StatusCode <> 200 then raise Exception.Create(response.StatusText);
finally
stream.Free;
end;
end)
.SetParameter(\'httpclient\',(TJsonHttpClient.Create),True)
.SetParameter(\'url\',\'https://mydom*ain.**com/testfile\')
.WaitAndRetry(5,250,2)
.OnRetry(
procedure(task : ITask; aException : Exception; var vStopRetries : Boolean)
begin
//if error 404 don\'t try to retry request
if task.Result = 404 then vStopRetries := True;
end)
.OnException(
procedure(task : ITask; aException : Exception)
begin
coutFmt(\'Exception downloading (Error: %s / StatusCode: %d)...\',[aException.Message,task.Result.AsInteger],etError);
end)
.OnTerminated(
procedure(task : ITask)
begin
if task.Done then coutFmt(\'Download \"%s\" finished ok\',[task[\'url\'].AsString],etSuccess)
else coutFmt(\'Download \"%s\" failed after %d retries\',[task[\'url\'].AsString,task.NumRetries],etError);
end)
.Run;
TBackgroundsTasks: Launch tasks in background allowing number of concurrent workers with fault and retry control policies. Use AddTask_Sync and OnTerminate_Sync methods if code needs to update UI.
-
Add a task to execute:
- AddTask: Specify Task name, parameters to pass to anonymous method(If OwnedParams=true, task will free params on expiration task) and method than will be executed.
- AddTask_Sync: Like AddTask but runs code with synchronize thread method (avoids problems if your code updates UI).
- SetParameter: Defines values or objects needed by your task. Every parameter will be accesible into anomymous methods defines as task[] or task.[index]
-
Define events to control:
- OnInitialize: Specify code to run before main execute task (this code only runs one time, OnExecute can be retried more than one time)
- OnRetry: Specify code to run when execution fails and decide if needs to retry or cancel next retries.
- OnTerminate: Specify code to execute when task finishes.
- *OnTerminate_Sync: Like OnTerminate but runs code with syncronized thread method (avoids problems if your code updates UI).
- OnException: Specify code to execute when task generates an exception.
-
Define fail/retry policies:
- RetryForever: If execution fails, code will be retry forever until task executes ok.
- Retry: If execution fails, code will be retry x times. Allow define array of milliseconds as wait time.
- WaitAndRetry: If execution fails, code will be retry x times, and wait x millisecons before each retry. You can specify number of retries and wait time between retries.
-
Begin execution:
- Start: Starts tasks execution.
backgroundtasks := TBackgroundTasks.Create(10); for i := 1 to 100 do begin mytask := TMyTask.Create; mytask.Id := i; mytask.Name := \'Task\' + i.ToString; backgroundtasks.AddTask([mytask],False, procedure(task : ITask) begin cout(\'task %d started\',[TMyTask(task.Param[0].AsObject).Id],etDebug); TMyTask(task.Param[0].AsObject).DoJob; end ).WaitAndRetry([250,2000,10000]) ).OnException( procedure(task : ITask; aException : Exception) begin cout(\'task %d failed (%s)\',[TMyTask(task.Param[0].AsObject).Id,aException.Message],etError); end ).OnTerminated( procedure(task : ITask) begin cout(\'task %d finished\',[TMyTask(task.Param[0].AsObject).Id],etDebug); TMyTask(task.Param[0].AsObject).Free; end ).Run; end; backgroundtasks.Start;
TScheduledTasks: Alternative to Timer. You can assign tasks with start time, repeat options and expiration date and fail and retry control policies. Use AddTask_Sync, OnTerminate_Sync and OnExpired_Sync if code needs to update UI.
You can assign anonymous methods to execute, exception, terminate and expiration events.
-
Add a task to execute:
- AddTask: Specify Task name, parameters to pass to anonymous method(If OwnedParams=true, task will free params on expiration task) and method than will be executed.
- AddTask_Sync: Like AddTask but runs code with synchronize thread method (avoids problems if your code updates UI).
- SetParameter: Defines values or objects needed by your task. Every parameter will be accesible into anomymous methods defines as task[] or task.[index]
-
Define events to control:
- OnInitialize: Specify code to run before main execute task (this code only runs one time, OnExecute can be retried more than one time)
- OnRetry: Specify code to run when execution fails and decide if needs to retry or cancel next retries.
- OnTerminate: Specify code to execute when task finishes.
- OnTerminate_Sync: Like OnTerminate but runs code with syncronized thread method (avoids problems if your code updates UI).
- OnExpire: Specify code to execute when task expiration reached or task was cancelled.
- OnExpire_Sync: Like OnExpire but runs code with synchronized thread method (avoids problems if your code updates UI).
- OnException: Specify code to execute when task generates an exception.
-
Define when to start task:
- StartNow: Start task immediately.
- StartAt: Date and time to start task.
- StartTodayAt: Start task today at defined time.
- StartTomorrowAt: Start task tomorrow at defined time.
- StartOnDayChange: Start task when day changes.
- StartInMinutes: Start task after x minutes.
- StartInSeconds: Start task after x seconds.
-
Define if needs to repeat or not (if not defined a previous StartAt, StartOn, etc, task will be executed immediately):
- RunOnce: Task will be executed one time only.
- RepeatEvery: Can indicate repeat step over time and expiration date.
- RepeatEveryDay: Repeat task every day at same hour.
- RepeatEveryWeek: Repeat task every week at same hour.
-
Define fail/retry policies:
- RetryForever: If execution fails, code will be retry forever until task executes ok.
- Retry: If execution fails, code will be retry x times.
- WaitAndRetry: If execution fails, code will be retry x times, and wait x millisecons before each retry. You can specify number of retries and wait time between retries.
-
Start/Stop scheduler:
- Start: Starts scheduler.
- Stop: Stops scheduler.
myjob := TMyJob.Create; myjob.Name := Format(\'Run at %s and repeat every 1 second until %s\',[DateTimeToStr(ScheduledDate),DateTimeToStr(ExpirationDate)]); scheduledtasks.AddTask(\'Task1\',[myjob],True, procedure(task : ITask) begin cout(\'task \"%s\" started\',[TMyTask(task.Param[0]).Name],etDebug); TMyJob(task.Param[0]).DoJob; end ).OnException( procedure(task : ITask; aException : Exception) begin cout(\'task \"%s\" failed (%s)\',[TMyJob(task.Param[0]).Name,aException.Message],etError); end ).OnTerminated( procedure(task : ITask) begin cout(\'task \"%s\" finished\',[TMyJob(task.Param[0]).Name],etDebug); end ).OnExpired( procedure(task : ITask) begin cout(\'task \"%s\" expired\',[TMyJob(task.Param[0]).Name],etWarning); end ).StartAt(ScheduledDate ).RepeatEvery(1,TTimeMeasure.tmSeconds,ExpirationDate); scheduledtasks.Start;
-
ITask: Interface passed to every task event of TRunTask, TBackgroundTasks and TScheduledTasks.
- NumWorker: Return number of worker assigned to execute task.
- Result: Can store any value type (TFlexValue is like variant type)
- Param[name]: Can store parameters passed to task or created dynamically into every anonymous methods passed to each event.
- Param[index]: Can store parameters passed to task or created dynamically into every anonymous methods passed to each event.
- Done: Return true is task is executed without errors.
- Failed: Return true is task has failed.
- IdTask: Task id defined.
- NumRetries: Number of retries done.
- MaxRetries: Number of maximum retries allowed before mark task as failed.
- LastException: Return last exception of a failed task.
- CircuitBreaked: Return true if max retries has been reached or user cancelled into OnRetry event.
- IsEnabled: Return status of task.
Quick.FaultControl:
Manages fail and retry policies, defining max retries, wait time beetween retries and circuit break mecanism.
Quick.Process:
Manages windows processes.
//kill explorer process KillProcess(\'explorer.exe\'); //determine if an application is running if IsProcessRunning(\'explorer.exe\') then Showmessage(\'Explorer is running!\'); //get username who is running an exe writeln(\'Explorer.exe open by: \' + GetProcessUser(\'explorer.exe\'); //gets handle of a window with a 20 seconds timeout if FindWindowTimeout(\'MainWindow\',20) then writeln(\'Window detected\');
Quick.Services:
Manages windows services.
//detect if a service is installed if not ServiceIsPresent(\'localhost\',\'MySvc\') then raise Exception.Create(\'Service not installed!\'); //Start a service ServiceStart(\'localhost\',\'MySvc\'); //Uninstall a service ServiceUninstall(\'MySvc\');
Quick.Format:
String format.
//Format bytes to MB, GB, TB... FormatBytes(50000) //shows 50KB FormatBytes(90000000) //shows 90MB
Quick.JsonSerializer:
Serializes an object from/to json text. You can define if public or published will be processed (only Delphi, fpc rtti only supports published properties)
json := \'{\"name\":\"Peter\",\"age\":30}\'; serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty); try serializer.JsonToObject(user,json); finally serializer.Free; end;
Quick.AutoMapper:
Map fields from one class to another class. Allows custom mappings to match different fields and custom mapping procedure to cast/convert fields manually.
//Map values from User1 to User2 TMapper<TUser2>.Map(User); //Map custom mappings AutoMapper := TAutoMapper<TUser,TUser2>.Create; //option1: you can define auto map different named properties AutoMapper.CustomMapping.AddMap(\'Cash\',\'Money\'); AutoMapper.CustomMapping.AddMap(\'Id\',\'IdUser\'); //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);
Quick.JsonRecord:
Used as a DTO class, with json serialize and mapping functions included.
下载源码
通过命令行克隆项目:
git clone https://github.com/exilon/QuickLib.git
