Quick Library 簡介

海利鸟發表於2024-05-13

QuickLib 是一個快速開發庫

QuickLib是一個快速開發庫,它提供了諸如AutoMapper、LinQ、IOC依賴注入、MemoryCache、計劃任務、Json和Yml配置、序列化程式等多種功能。這個庫特別支援Delphi和Firemonkey的多平臺開發,包括Windows、Linux、Android、OSX和IOS。同時,QuickLib也支援freepascal,使得開發人員能夠更輕鬆地構建跨平臺應用程式並提高生產力。

功能領域:

  • 對映(Mapping): 將一個類的欄位對映到另一個類,複製物件等。
  • 配置(Config): 將配置作為物件使用,並從/向檔案(Json/Yaml)或Windows登錄檔載入/儲存。
  • 序列化(Serialization): 將物件序列化到/從json/Yaml。
  • 排程(Scheduling): 以獨立執行緒啟動任務,並具有重試策略。
  • 執行緒(Threading): 簡化多執行緒後臺任務的執行和控制,執行緒安全的列表、佇列等
  • 資料(Data): 靈活的資料交換和儲存,允許多種輸入輸出型別。
  • 雲(Cloud): 簡化雲Azure/Amazon檔案管理,傳送電子郵件等。
  • 查詢(Querying): 索引列表,可搜尋列表和用於通用列表和陣列的Linq查詢系統。
  • 基準測試(Benchmark): 經過的時間控制和基準測試功能。
  • 檔案系統(Filesystem): 程序和服務控制,檔案修改監視器和助手等...
  • 失敗控制(FailControl): 失敗和重試策略。
  • 快取(Caching): 快取字串或物件,以便稍後快速檢索。
  • 模板(Templating): 使用字典進行簡單的字串模板化。
  • 除錯(Debuging): 用於除錯程式碼的工具。
  • 引數(Parameters): 使用命令列引數。

主要單元描述:

  • Quick.Commons: 開發人員日常工作中經常需要的功能。
  • Quick.AppService: 允許控制檯應用程式以控制檯模式或服務模式執行相同的程式碼,從而簡化除錯任務。
  • Quick.Azure/Amazon: 簡化了與Azure和Amazon雲端儲存的blob互動。
  • Quick.Network: CIDR和IP範圍功能。
  • Quick.Chrono: 計時器和基準測試一段程式碼很簡單。
  • Quick.Console: 使用顏色等將日誌訊息寫入控制檯...
  • Quick.Log: 以詳細級別和每日或最大空間輪換方式記錄到磁碟或記憶體。
  • Quick.Config: 將配置載入/儲存為Json或Yaml檔案或Windows登錄檔項,並將其作為物件管理。
  • Quick.FileMonitor: 監視檔案的更改並丟擲事件。
  • Quick.JsonUtils: 用於處理json物件的工具。
  • Quick.SMTP: 用兩行程式碼傳送電子郵件。
  • Quick.Threads: 執行緒安全類,具有重試策略的排程和後臺任務。
  • Quick.Process: 管理Windows程序。
  • Quick.Services: 管理Windows服務。
  • Quick.Format: 字串格式。
  • Quick.RTTI.Utils: 簡化與RTTI的工作。
  • Quick.JsonSerializer: 將物件序列化到/從json文字。您可以定義是否將處理公開或釋出的屬性(僅Delphi,fpc rtti僅支援已釋出的屬性)
  • Quick.AutoMapper: 將一個類的欄位對映到另一個類。允許自定義對映以匹配不同的欄位,以及手動轉換/轉換欄位的自定義對映過程。
  • Quick.JsonRecord: 用作DTO類,包含json序列化和對映功能。
  • Quick.Lists: 具有索引或搜尋功能的改進列表。
  • Quick.Value FlexValue儲存任何資料型別,並允許使用整合運算子和autofrees將其傳遞給其他類。
  • Quick.Arrays: 改進的陣列。
  • Quick.YAML: Yaml物件結構。
  • Quick.YAML.Serializer: 將物件從/序列化為Yaml。
  • Quick.Expression: 使用表示式評估物件屬性。
  • Quick.Linq: 對任何TObjectList,TList,TArray和TXArray進行Linq查詢,執行類似SQL語法的複雜Where選擇,更新和排序列表。
  • Quick.MemoryCache: 快取具有過期時間的物件/資訊,以避免每次需要時都生成這些資訊(資料庫查詢,難以計算的資訊等)。
  • Quick.Collections: 集合改進,如具有Linq繼承的IList和IObjectList。
  • Quick.Pooling: 建立物件池以避免外部資源消耗殆盡和開銷。
  • Quick.Template: 使用字典或委託替換字串模板。
  • Quick.Debug.Utils: 簡單的除錯和程式碼基準測試工具。
  • Quick.Parameters: 將命令列引數作為一個類來處理。
  • Quick.Url.Utils: 簡單的URL操作
  • Quick.RegEx.Utils: 常用的RegEx比較(電子郵件驗證,密碼複雜性等)
  • Quick.Conditions: 流暢風格的前後條件驗證。

Quick.AppService

允許控制檯應用程式以控制檯模式或服務模式執行相同的程式碼,從而簡化除錯任務。

if not AppService.IsRunningAsService then
begin
    ...你的程式碼以控制檯模式執行
end
else
begin
    AppService.ServiceName := 'MyService';
    AppService.DisplayName := 'MyServicesvc';
    //你可以將匿名方法傳遞給事件
    AppService.OnStart := procedure
                          begin
                            ...你的啟動程式碼
                          end;
    AppService.OnExecute := YourExecuteFunction;
    AppService.OnStop := YourStopFunction;
    AppService.CheckParams;
end;

Quick.Azure/Amazon:

簡化了與Azure和Amazon雲端儲存的blob互動。

//連線到Azure blob儲存
QuickAzure := TQuickAzure.Create(AzureAccountName, AzureAccountKey);

//將blob檔案下載到流中
done := QuickAzure.GetBlob('MyContainer', 'MyFile.jpg', ResponseInfo, MyStream);
  
//檢查是否存在資料夾
found := ExistFolder('MyContainer', '/Public/Documents/Personal');
  
//列出以特定模式開頭的blobs(遞迴或非遞迴)
for azBlob in ListBlobs('MyContainer', '/Public/Documents', Recursive, ResponseInfo) do
begin
    if azBlob.Size > 1000 then Showmessage(azBlob.Name);
end;

Quick.Network:

提供CIDR和IP範圍功能。

//將IP字串轉換為整數
IPv4ToInt('192.168.1.10');

//獲取子網範圍的第一個和最後一個IP
GetIpRange('192.168.100.0', '255.255.255.0', LowIp, HighIP);

Quick.Commons:

開發人員日常工作中經常需要的函式。

//將UTC時間TDateTime轉換為本地日期時間
UTCToLocalTime(MyUTCTime);
  
//生成一個長度為10的隨機密碼,包含字母數字和符號。
RandomPassword(10, [pfIncludeNumbers, pfIncludeSigns]);

//將短語中的每個單詞首字母大寫
CapitalizeAll('the grey fox'); //返回 "The Grey Fox"

//簡單的TCounter和TTimeCounter用於迴圈
counter := TCounter;
counter.Init(200);
timecounter : TTimeCounter;
timecounter.Init(10000);
while true do
begin
    Inc(n);
    {你的過程處理程式碼在這裡}
    //每200步寫入控制檯
    if counter.Check then writeln(Format('Processed %d entries', [n]));
    //每10秒寫入控制檯
    if timecounter.Check then writeln('Im working...'); 
end;

Quick.Chrono:

計時器和程式碼基準測試很簡單。

//獲取程式碼部分執行所消耗的時間
Chrono := TChronometer.Create(False);
Chrono.Start;
...你需要基準測試的程式碼
Chrono.Stop;

//以長時間格式顯示經過的時間(例如2小時10分鐘)
Showmessage(Chrono.TimeElapsed(True));

//以短時間格式顯示經過的時間(例如02:10:00)
Showmessage(Chrono.TimeElapsed(False));
//獲取程序的基準測試資訊
Chrono := TChronoBenchMark.Create;
Chrono.TotalProcess := 100000;
for i := 1 to 10000 do
begin
    {你的程序程式碼在這裡}
    Chrono.CurrentProcess := i;
    //顯示你的程序預計需要的時間,格式為x小時x分鐘x秒
    writeln(Chrono.EstimatedTime(True));
    //顯示你的程序處理速度:每秒處理的項數
    writeln(Format('Items processed %d/sec', [Chrono.Speed]));
end;
writeln(Chrono.ElapsedTime(False)); //以00:00:00格式顯示總經過時間

Quick.Console:

將日誌訊息以不同顏色等寫入控制檯。

//定義需要的輸出級別
Console.Verbose := LOG_DEBUG;

//以紅色在控制檯上寫行
cout('Error x', etError); 

//以綠色格式化輸出行
coutFmt('Proccess %s finished', [ProccesName], etSuccess);

//寫整數
cout(12348);

//連線QuickLog並一行程式碼同時寫入磁碟和螢幕(具有獨立的詳細級別)
MyQuickLog := TQuickLog.Create;
MyQuickLog.Verbose := LOG_ALL;
Console.Verbose := LOG_ONLYERRORS;
Console.Log := MyQuickLog;

Quick.Log:

記錄到磁碟或記憶體,具有詳細的日誌等級和每日或最大空間輪換功能。

// 在開始時寫入包含執行路徑、應用程式名稱、除錯模式、使用者等資訊的頁首
Log.ShowHeader := True;// 設定20MB時輪換的日誌
Log.SetLog('.\mylog.log',False,20);// 寫入一條錯誤資訊
Log.Add('Error x',etError);// 寫入格式化的錯誤資訊
Log.Add('Error is %s',[ErrorStr],etError);Quick.Config:
以Json、Yaml檔案或Windows登錄檔項的形式載入/儲存配置。從TAppConfigJson、TAppConfigYaml或TAppConfigRegistry建立一個派生類,並新增將載入/儲存的已釋出的屬性。當檢測到檔案更改時,可以重新載入檔案配置。// 建立一個類繼承
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;// 將配置建立為json檔案
// 在您的uses中新增Quick.Config.Json
MyConfig := TMyConfig.Create('Config.json');
MyConfig.Provider.CreateIfNotExists := True;
MyConfig.Provider.ReloadIfFileModified := True;
MyConfig.Name := 'John';
MyConfig.Surname := 'Smith';
// 載入
MyConfig.Load;
// 儲存
MyConfig.Save;// 將配置建立到Windows登錄檔中
// 在您的uses中新增Quick.Config.Registry
MyConfig := TMyConfig.Create;
// 將登錄檔定義為HKEY_CURRENT_USER\Software\MyApp
MyConfig.HRoot := HKEY_CURRENT_USER;
MyConfig.MainKey := 'MyApp';
MyConfig.Name := 'John';
MyConfig.Surname := 'Smith';
// 載入
MyConfig.Load;
// 儲存
MyConfig.Save;// 建立一個沒有預設提供者的自定義配置
TMyConfig = class(TAppConfig)
... 您的屬性
end;MyConfig := TMyConfig.Create(TAppConfigJsonProvider.Create('.\config.json');

Quick.FileMonitor:

監視檔案的更改並觸發事件。

FileMonitor.Filename := '.\myfile.txt';
// 每2秒檢查一次檔案更改
FileMonitor.Interval := 2000;
// 監視檔案被刪除或修改的事件
FileMonitor.Notifies := [mnFileModified, mnFileDeleted)];
FileMonitor.OnFileChange := MyFileChangeFunction;
FileMonitor.Enabled := True;

Quick.JsonUtils:

用於處理json物件的工具。

// 當在uses中宣告單元時,TObject Helper允許將所有物件從/載入到json字串
MyObject.FromJson := jsonstring;
MyString := MyObject.ToJson;// 您可以使用clone函式克隆簡單物件
MyObject1.Clone(MyObject2);

Quick.SMTP:

用兩行程式碼傳送電子郵件。

// 傳送電子郵件
SMTP := TSMTP.Create('mail.domain.com',25,False);
SMTP.SendMail('my@email.com','to@email.com','Email subject','My message body');// 您可以定義更高階的選項
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:

執行緒安全類。

TThreadedQueueCS: 使用臨界區的TThreadedQueue版本。

TThreadObjectList: 執行緒安全的物件列表。

TThreadedQueueList: 執行緒安全的佇列列表。支援自動增長和臨界區。

TAnonymousThread: 建立匿名執行緒,定義非鏈式的Execute和OnTerminate方法。如果程式碼需要更新UI,請使用Execute_Sync和OnTerminate_Sync方法。

  • Execute: 指定啟動時執行的程式碼。
  • Execute_Sync: 與Execute類似,但使用同步執行緒方法執行程式碼(避免如果程式碼更新UI時出現問題)。
  • OnTerminate: 指定任務完成時執行的程式碼。
  • OnTerminate_Sync: 與OnTerminate類似,但使用同步執行緒方法執行程式碼(避免如果程式碼更新UI時出現問題)。
  • Start: 啟動執行緒執行。
// 簡單的匿名執行緒
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: 啟動一個自動釋放的單任務執行緒,具有故障和重試控制策略。可以在程式碼中傳遞和建立引數。

  • 定義要執行的程式碼:
    • Execute: 指定任務名稱、傳遞給匿名方法的引數(如果OwnedParams=true,任務將在終止時釋放引數)以及將要執行的方法。
    • Execute_Sync: 與Execute類似,但使用同步執行緒方法執行程式碼(避免如果程式碼更新UI時出現問題)。
    • SetParameter: 定義任務所需的值或物件。
  • 定義控制事件:
    • OnInitialize: 在主執行任務之前執行指定的程式碼(此程式碼僅執行一次,OnExecute可以重試多次)
    • OnRetry: 當執行失敗時指定要執行的程式碼,並決定是否需要重試或取消後續重試。
    • OnTerminate: 指定任務完成時執行的程式碼。
    • OnTerminate_Sync: 與OnTerminate類似,但使用同步執行緒方法執行程式碼(避免如果程式碼更新UI時出現問題)。
    • OnException: 當任務引發異常時指定要執行的程式碼。
  • 定義故障/重試策略:
    • RetryForever: 如果執行失敗,程式碼將無限次重試,直到任務執行成功。
    • Retry: 如果執行失敗,程式碼將重試x次。
    • WaitAndRetry: 如果執行失敗,程式碼將重試x次,並在每次重試之前等待x毫秒。您可以指定重試次數和重試之間的等待時間。
    • Run: 啟動任務執行。
  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://mydomain.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: 在後臺啟動任務,允許一定數量的併發工作執行緒,並具有故障和重試控制策略。如果程式碼需要更新UI,請使用AddTask_Sync和OnTerminate_Sync方法。

  • 新增要執行的任務:
    • AddTask: 指定任務名稱、傳遞給匿名方法的引數(如果OwnedParams=true,任務將在過期時釋放引數)以及將要執行的方法。
    • AddTask_Sync: 與AddTask類似,但使用同步執行緒方法執行程式碼(避免如果程式碼更新UI時出現問題)。
    • SetParameter: 定義任務所需的值或物件。每個引數都將在匿名方法中作為task[<name>]或task.[index]訪問。
  • 定義控制事件:
    (與TRunTask類似,此處省略)
  • 定義故障/重試策略:
    (與TRunTask類似,此處省略)
  • 開始執行:
    • Start: 開始執行任務。
    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: 定時器的替代方案。您可以分配具有開始時間、重複選項、到期日期和故障及重試控制策略的任務。如果程式碼需要更新UI,請使用AddTask_Sync、OnTerminate_Sync和OnExpired_Sync方法。
您可以為執行、異常、終止和到期事件分配匿名方法。

  • 新增要執行的任務:
    (與TRunTask和TBackgroundTasks類似,此處省略)
  • 定義控制事件:
    (與TRunTask類似,但增加了OnExpire和OnExpire_Sync)
  • 定義何時開始任務:
    • StartNow: 立即啟動任務。
    • StartAt: 任務啟動的日期和時間。
    • ...(其他開始選項,此處省略)
  • 定義是否需要重複或不重複(如果未定義之前的StartAt、StartOn等,任務將立即執行):
    • RunOnce: 任務僅執行一次。
    • RepeatEvery: 可以指示重複步驟的時間間隔和到期日期。
    • ...(其他重複選項,此處省略)
  • 定義故障/重試策略:
    (與TRunTask類似,此處省略)
  • 啟動/停止排程器:
    • Start: 啟動排程器。
    • Stop: 停止排程器。
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: 傳遞給TRunTask、TBackgroundTasks和TScheduledTasks的每個任務事件的介面。

  • NumWorker: 返回分配給執行任務的工作執行緒數。
  • Result: 可以儲存任何值型別(TFlexValue類似於變體型別)
  • Param[name]: 可以儲存傳遞給任務的引數或在每個傳遞給事件的匿名方法中動態建立的引數。
  • Param[index]: 可以儲存傳遞給任務的引數或在每個傳遞給事件的匿名方法中動態建立的引數。
  • Done: 如果任務沒有錯誤地執行,則返回true。
  • Failed: 如果任務失敗,則返回true。
  • IdTask: 定義的任務ID。
  • NumRetries: 已完成的重試次數。
  • MaxRetries: 在將任務標記為失敗之前允許的最大重試次數。
  • LastException: 返回失敗任務的最後一個異常。
  • CircuitBreaked: 如果已達到最大重試次數或在OnRetry事件中使用者取消了重試,則返回true。
  • IsEnabled: 返回任務的狀態。

Quick.FaultControl:

管理失敗和重試策略,定義最大重試次數、重試之間的等待時間和熔斷機制。

Quick.Process:

管理Windows程序。

// 終止explorer程序
KillProcess('explorer.exe');
// 判斷一個應用程式是否正在執行
if IsProcessRunning('explorer.exe') then Showmessage('Explorer正在執行!');
// 獲取執行exe的使用者名稱
writeln('Explorer.exe由以下使用者開啟:' + GetProcessUser('explorer.exe'));
// 使用20秒的超時獲取視窗控制代碼
if FindWindowTimeout('MainWindow',20) then writeln('檢測到視窗');

Quick.Services:

管理Windows服務。

// 檢測服務是否已安裝
if not ServiceIsPresent('localhost','MySvc') then raise Exception.Create('服務未安裝!');
// 啟動服務
ServiceStart('localhost','MySvc');
// 解除安裝服務
ServiceUninstall('MySvc');

Quick.Format:

字串格式化。

// 將位元組格式化為MB、GB、TB...
FormatBytes(50000) // 顯示 50KB
FormatBytes(90000000) // 顯示 90MB

Quick.JsonSerializer:

將物件序列化為json文字或從json文字反序列化為物件。您可以定義是否處理公開或已釋出的屬性(僅Delphi,fpc rtti僅支援已釋出的屬性)。

json := '{"name":"Peter","age":30}';
serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
try
   serializer.JsonToObject(user,json);
finally
   serializer.Free;
end;

Quick.AutoMapper:

將一個類的欄位對映到另一個類。允許自定義對映以匹配不同的欄位,並允許自定義對映過程以手動轉換欄位。

// 將User1的值對映到User2
TMapper<TUser2>.Map(User);

// 自定義對映
AutoMapper := TAutoMapper<TUser,TUser2>.Create;

// 選項1:您可以定義自動對映不同名稱的屬性
AutoMapper.CustomMapping.AddMap('Cash','Money');
AutoMapper.CustomMapping.AddMap('Id','IdUser');

// 選項2:您可以決定手動修改每個屬性或允許自動對映某些屬性
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;

// 選項3:您可以在自動對映完成後修改某些屬性
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:

用作DTO類,包含json序列化和對映功能。

type
   TUser = class(TJsonRecord)
   private
      fName : string;
      fAge : Integer;
   published
      property Name : string read fName write fName;
      property Age : Integer read fAge write fAge;
   end;
var
   user, user2 : TUser;
begin
   user := TUser.Create;
   // 展示為json字串
   Writeln(user.ToJson);
   // 對映到其他類
   user.MapTo(user2);
   Writeln(user2.ToJson);
   // 從檔案載入
   user.LoadFromFile('.\user.json');
   // 儲存到檔案
   user2.SaveToFile('.\user2.json');
end;

Quick.Lists:

帶有索引或搜尋功能的改進列表。

  • TIndexedObjectList: 允許透過物件屬性或欄位進行快速雜湊搜尋。
  • TSearchObjectList: 允許透過物件屬性或欄位進行迭代搜尋。
var
   users : TIndexedObjectList<TUser>;
begin
   users := TIndexedObjectList<TUser>.Create(True);
   // 根據屬性"Name"建立索引
   users.Indexes.Add('Name','Name',TClassField.cfProperty);
   // 根據私有欄位"Id"建立索引
   users.Indexes.Add('Id','fId',TClassField.cfField);
   // 透過"Name"索引獲取使用者
   writeln(users.Get('Name','Peter').SurName);
end;

Quick.Value

FlexValue可以儲存任何資料型別,並允許使用整合運算子和自動釋放功能傳遞給其他類。

var
  value : TFlexValue;
  str : string;
  num : Integer; 
begin
  value := 'hello';
  str := value;
  value := 123;
  num := value;
end;

Quick.Arrays:

改進的陣列。

TXArray: 帶有類似TList方法的陣列。

(注意:下面的程式碼段似乎被錯誤地複製了 TIndexedObjectList的示例,這裡應該展示 TXArray的使用。)

var
   users : TXArray<TUser>;
begin
   users := TXArray<TUser>.Create;
   users.Add(User); // 假設User已經是一個TUser型別的物件
   // ... 其他TXArray的操作
end;

TFlexArray: 可以儲存不同值型別的陣列,類似於TList。

var
  flexarray : TFlexArray;
begin
    flexarray.Add(10);
    flexarray.Add('Hello');
    user := TUser.Create;
    try
      user.Name := 'Joe';
      flexarray.Add(user);

      cout('Integer Item = %d',[flexarray[0].AsInteger],etInfo);
      cout('String Item = %s',[flexarray[1].AsString],etInfo);
      cout('Record Item = %s',[TUser(flexarray[2]).Name],etInfo);
    finally
      user.Free;
    end;
end;

TFlexPairArray: 可以儲存不同值型別的陣列,並可以透過專案名稱進行搜尋,類似於TList。

var
  flexarray : TFlexPairArray;
begin
    flexarray.Add('onenumber',10);
    flexarray.Add('other','Hello boy!');
    user := TUser.Create;
    try
      user.Name := 'Joe';
      flexarray.Add('myuser',user);

      cout('Integer Item = %d',[flexarray.GetValue('onenumber').AsInteger],etInfo);
      cout('String Item = %s',[flexarray.GetValue('other').AsString],etInfo);
      cout('Record Item = %s',[TUser(flexarray.GetValue('myuser')).Name],etInfo);
    finally
      user.Free;
    end;
end;

Quick.YAML:

Yaml物件結構。

TYamlObject: Yaml物件是一個Yaml值對的陣列。

// 從yaml文字建立Yaml物件
yamlobj.ParseYamlValue(aYaml);
// 新增一個對
yamlobj.AddPair('Name','Mike');
// 顯示為yaml結構
Writeln(yamlobj.ToYaml);

TYamlArray: 物件或標量的陣列。

yamlarray.AddElement(TYamlPair.Create('Age',30));
yamlobj.AddPair('myarray',yamlarray);

TYamlPair: 名稱-值對。值可以是物件、陣列或標量。

n := yamlobj.GetPair('Name').Value as TYamlInteger;

Quick.YAML.Serializer:

將物件序列化/反序列化為Yaml。

// 序列化
text := YamlSerializer.ObjectToYaml(obj);
// 反序列化
YamlSerializer.YamlToObject(obj, yamltext);

Quick.Expression:

使用表示式評估物件屬性或單個值。

if TExpressionParser.Validate(user, '(Age > 30) AND (Dept.Name = "Financial")') then
begin
  // 執行一些操作
end;

if TExpressionParser.Validate(user, '(20 > 30) OR (5 > 3)') then
begin
  // 執行一些操作
end;

Quick.Linq:

對任何 TObjectList<T>TList<T>TArray<T>TXArray<T>執行Linq查詢,透過類似SQL語法的複雜Where子句進行Select、更新和排序列表。Where子句使用名稱空間來確定巢狀屬性。Linq可以在屬性陣列中搜尋元素。
現在包括一個 TArray<string>助手,用於在陣列中新增、刪除和透過正規表示式搜尋。

  • From: 要使用的陣列、XArray或TObjectList。
  • Where: 搜尋表示式。可以使用點來定義屬性路徑。
  • SelectAll: 返回匹配Where子句的物件陣列。
  • SelectTop: 返回匹配Where子句的前x個物件。
  • SelectFirst: 返回匹配Where子句的第一個物件。
  • SelectLast: 返回匹配Where子句的最後一個物件。
  • OrderBy: 定義返回列表的順序。
  • Update: 更新匹配Where子句的欄位。
  • Delete: 刪除匹配Where子句的物件。
  • Count: 返回匹配Where子句的元素數量。
// 多條件選擇
for user in TLinq<TUser>.From(userslist).Where('(Name = ?) OR (SurName = ?) OR (SurName = ?)', ['Peter', 'Smith', 'Huan']).Select do
begin
  // 執行一些操作
end;

// 選擇並更新欄位
TLinq<TUser>.From(userlist).Where('SurName Like ?', ['%son']).SelectFirst.Name := 'Robert';

// 選擇頂部並按欄位排序
for user in TLinq<TUser>.From(userlist).Where('Age > ?', [18]).SelectTop(10).OrderBy('Name') do
begin
  // 執行一些操作
end;

// 按條件更新欄位
TLinq<TUser>.From(userlist).Where('Name = ?', ['Peter']).Update(['Name'], ['Joe']);

// 計數結果
numusers := TLinq<TUser>.From(userlist).Where('(Age > ?) AND (Age < ?)', [30, 40]).Count;

Quick.HTTPServer:

TCustomHttpServer是一個簡單的介面HttpServer,具有自己的HttpRequest和HttpResponse實現,允許輕鬆更改HttpServer引擎。
您可以啟用自定義錯誤頁面以返回自定義頁面和動態錯誤頁面。
THttpServer是IndyHttpServer的實現,但您可以定義自己的實現。

TMyHttpServer = class(THttpServer)
public
  procedure ProcessRequest(aRequest: IHttpRequest; aResponse: IHttpResponse); override;
end;

procedure TMyHttpServer.ProcessRequest(aRequest: IHttpRequest; aResponse: IHttpResponse);
begin
  aResponse.ContentText := 'Hello world!';
end;

Quick.MemoryCache:

使用過期時間快取物件或字串,以避免每次需要時都生成這些資訊(資料庫查詢、難以計算的資訊等)。TMemoryCache允許快取物件和字串。泛型版本TMemoryCache <T>僅允許快取定義的型別。

  • 建立:可以定義清除間隔、序列化和壓縮引擎。預設情況下,它使用Json進行序列化並使用gzip進行壓縮。
// 建立具有10秒清除間隔的MemoryCache
cache := TMemoryCache.Create(10);

// 為特定型別建立MemoryCache
cache := TMemoryCache<TMyObj>.Create;
  • 壓縮:啟用/禁用快取資料壓縮。
  • CachedObjects:返回當前快取中的物件數量。
  • CacheSize:返回當前快取中所有物件的位元組大小。實際使用的記憶體取決於記憶體管理器或架構。此值是資料位元組的實際大小。
  • PurgeInterval:清除作業嘗試查詢已過期物件以從快取中刪除的時間間隔(預設值為20秒)。
  • OnCacheFlushed:當快取被重新整理時。
  • OnBeginPurgerJob:當清除作業開始時。
  • OnEndPurgerJob:當清除作業結束時。
  • Flush:刪除所有快取物件。
  • SetValue:將物件新增到快取。可以指示過期日期或毫秒數來過期。如果沒有定義,快取將是無限的。MemoryCache可以儲存物件或字串。
// 將字串設定到快取中,沒有過期時間
cache.SetValue('mystring', 'hello world');

// 將字串設定到快取中,10秒後過期
cache.SetValue('mystring', '這個快取將在10秒後過期');

// 將物件設定到快取中
cache.SetValue('Obj1', valueobj);
  • TryGetValue:嘗試從快取中獲取物件。如果物件不存在或已過期,則返回false。
// 獲取字串查詢結果
cache.GetValue('Query12');

// 獲取整數
cache.TryGetValue<Integer>('number', valueint);

// 獲取物件
cache.TryGetValue('Obj1', valueobj);
  • RemoveValue:從快取中刪除物件。
  • 快取引擎提供程式:
  • TCacheSerializerJSON:使用JSON序列化快取資料。
  • TCacheCompressorGzip:使用Gzip壓縮快取資料。
  • TCacheCompressorLZO:使用LZO壓縮快取資料。
// 建立具有20秒清除間隔並使用LZO引擎壓縮的MemoryCache
cache := TMemoryCache.Create(10, nil, TCacheCompressorLZO.Create);

Quick.IOC:

控制反轉管理器允許自動建立介面或例項化物件,或在建構函式類中自動注入它們,以避免依賴關係。

建立一個容器來管理依賴注入。

iocContainer := TIocContainer.Create;

註冊型別:

在注入之前,您需要註冊型別。型別可以作為Singleton或Transient註冊。
Singleton:生命週期將是所有注入的一個單一例項,類似於全域性變數。
Transient:生命週期將是每次注入的一個新例項。

將介面型別作為Transient註冊到容器中:

iocContainer.RegisterType<IMultService, TMultService>.AsTransient;

將介面型別作為Singleton註冊,並委託構造:

iocContainer.RegisterType<ISumService, TSumService>.AsSingleTon.DelegateTo(
  function : TSumService
  begin
    Result := TSumService.Create;
  end
);

註冊例項:

將命名例項物件作為Transient註冊,並委託構造:

iocContainer.RegisterInstance<TDivideService>('one').AsTransient.DelegateTo(
  function : TDivideService
  begin
    Result := TDivideService.Create(True);
  end
);

註冊選項:

註冊IOptions(僅適用於Singleton):

iocContainer.RegisterOptions<TMyOptions>(MyOptions);

解析型別:

AbstractFactory:
嘗試使用依賴注入解析所有建立方法引數來建立類。

MyClass := iocContainer.AbstractFactory<TMyBaseClass>(TMyClass);

解析介面依賴:

multservice := iocContainer.Resolve<IMultService>;
result := multservice.Mult(2, 4);

解析例項:

解析命名例項依賴:

divideservice := iocContainer.Resolve<TDivideService>('other');
result := divideservice.Divide(100, 2);

介面例項將自動釋放,但例項依賴項僅當定義為Singleton時才會被釋放,Transient例項將由程式碼銷燬。#3

Quick.Options:

您可以將部分定義為類,並將其儲存為單個檔案設定。其工作方式類似於dotnet Options。選項檔案可以是JSON或YAML格式。

定義從TOptions繼承的選項類,所有已釋出的屬性都將被載入/儲存。
建立選項容器,使用JsonSerializer並在更改時重新載入:

Options := TOptionsContainer.Create('.\options.conf', TJsonOptionsSerializer.Create, True);

向容器選項新增一個部分:

Options.AddSection<TLoggingOptions>('Logging');

配置選項:

您可以定義要儲存到檔案中的部分名稱,並委託配置預設設定和驗證值:

Options.AddSection<TLoggingOptions>('Logging').ConfigureOptions(
  procedure(aOptions: TLoggingOptions)
  begin
    aOptions.Path := 'C:\';
  end
).ValidateOptions;

驗證選項:

驗證選項允許驗證選項設定是否在定義的範圍內。此驗證需要先在TOptions類中的屬性上分配自定義屬性。

  • StringLength(max, messagestr): 允許在字串屬性中定義最大長度,如果長度大於最大值,則返回messagestr。
  • Range(min, max, messagestr): 允許定義允許的最小值和最大值範圍,如果值超出邊界,則返回messagestr。
TLoggingOptions = class(TOptions)
  private
    fPath : string;
  published
    [Required, StringLength(255, 'Path too long')]
    property Path : string read fPath write fPath;
    [Range(0.0, 5.2)]
    property Level : Double read fLevel write fLevel;
  end;

使用選項:
檢索選項部分:

LoggingOptions := Options.GetSection<TLoggingOptions>;
LoggingOptions.Path := 'C:\Path';

使用IOptions:
IOptions是一個可注入依賴的TOptions介面。您可以使用IocContainer.RegisterOptions <TOptions>註冊它以使其可注入到建構函式方法中。

UIOptions := Options.GetSectionInterface<TUIOptions>.Value;
UIOptions.WindowColor := clBlue;

載入/儲存選項:

從檔案設定中載入選項:

options.Load;

將選項儲存到檔案設定:

options.Save;

如果您在建立容器時定義了ReloadOnChanged引數為true,則每次檔案設定更改時,配置都將重新載入。如果您需要控制何時重新載入,可以監聽事件:

Options.OnFileModified := procedure
  begin
    cout('Detected config file modification!', etWarning);
  end;

Quick.Pooling:

定義連線池、執行緒池或您想要控制的任何物件池,以避免資源消耗,如資料庫連線、HTTP客戶端等。

建立HTTP客戶端池:

pool := TObjectPool<THTTPClient>.Create(5, 5000, procedure(var aInstance: THTTPClient)
        begin
          aInstance := THTTPClient.Create;
          aInstance.UserAgent := 'MyAgent';
        end);

從池中獲取物件:

httpcli := pool.Get.Item;
statuscode := httpcli.Get('https://www.mydomain.com').StatusCode;

Quick.Collections:

定義了具有linQ支援的介面List和ObjectList。

  • TXList <T> / IList <T>:允許使用LinQ進行正規表示式搜尋/刪除/更新的介面List。
myarray := ['Joe', 'Mat', 'Lee'];
// 搜尋正規表示式匹配項
cout('Search for regex match', ccYellow);
for name in myarray.Where('e$', True).Select do
begin
  cout('User %s ends with "e"', [name], etInfo);
end;
  • TXObjectList <T> / IObjectList <T>:允許使用LinQ謂詞或表示式進行搜尋/刪除/更新的介面ObjectList。
    表示式搜尋:
user := ListObj.Where('Profile.Name = ?', ['Lee']).SelectFirst;

對項陣列的表示式搜尋:

users := ListObj.Where('Roles CONTAINS ?', ['SuperAdmin']).Select;

謂詞搜尋:

user := ListObj.Where(function(aUser: TUser): Boolean
      begin
        Result := aUser.Name.StartsWith('J');
      end).SelectFirst;
    if user <> nil then cout('%s starts with J letter', [user.Name], etInfo);

檢視Quick.Linq部分以檢視更多允許的函式。

Quick.Template:

使用字典或委託函式進行字串模板替換。您可以指定引號的標記字元。

透過傳遞字典進行替換:

dict := TDictionary<string, string>.Create;
dict.Add('User', 'John');
dict.Add('Age', '20');
dict.Add('SurName', 'Peterson');
mytemplate := 'User {{User}} {{SurName}} are {{Age}} years old.';
template := TStringTemplate.Create('{{', '}}', dict);
Result := template.Replace(mytemplate);

使用委託函式進行替換:

mytemplate := 'User {{User}} {{SurName}} are {{Age}} years old.';
template := TStringTemplate.Create('{{', '}}', function(const aToken: string): string
  begin
    if aToken = 'User' then Result := 'John'
    else if aToken = 'SurName' then Result := 'Peterson'
    else if aToken = 'Age' then Result := '20';
  end);
Result := template.Replace(mytemplate);

Quick.Debug.Utils:

除錯工具,用於檢查效能並獲取進入和退出方法的檢查點。透過Debug編譯器指令定義,僅在應用程式以除錯模式編譯時啟用。
在控制檯應用程式中,預設使用控制檯輸出。您可以傳遞一個記錄器以輸出到:

TDebugUtils.SetLogger(ilogger);

跟蹤程式碼的一部分:

function TCalculator.Subs(a, b: Int64): Int64;
begin
  {$IFDEF DEBUG}
  TDebugger.Trace(Self, Format('Substract %d - %d', [a, b]));
  {$ENDIF}
  Result := a - b;
  // 模擬工作200毫秒
  Sleep(200);
end;
// 返回:
// 29-06-2020 23:31:41.391  [TRACE] TCalculator -> Substract 30 - 12

計算從點到退出函式的處理時間:

function TCalculator.Sum(a, b: Int64): Int64;
begin
  {$IFDEF DEBUG}
  TDebugger.TimeIt(Self, 'Sum', Format('Sum %d + %d', [a, b]));
  {$ENDIF}
  Result := a + b;
  // 模擬工作1秒
  Sleep(1000);
end;
// 返回:
// 29-06-2020 22:58:45.808  [CHRONO] TCalculator.Sum -> Sum 100 + 50 = 1,00s

計算從點到點以及退出函式的處理時間:

function TCalculator.Divide(a, b: Int64): Double;
begin
  {$IFDEF DEBUG}
  var crono := TDebugger.TimeIt(Self, 'Divide', Format('Divide %d / %d', [a, b]));
  {$ENDIF}
  Result := a / b;
  // 模擬工作500毫秒
  Sleep(500);
  {$IFDEF DEBUG}
  crono.BreakPoint('Only divide');
  {$ENDIF}
  // 模擬工作1秒
  Sleep(1000);
  {$IFDEF DEBUG}
  crono.BreakPoint('Only Sleep');
  {$ENDIF}
end;
// 返回:
// 29-06-2020 23:25:46.223  [CHRONO] TCalculator.Divide -> First point = 500,18ms
// 29-06-2020 23:25:47.224  [CHRONO] TCalculator.Divide -> Second point = 1,00s
// 29-06-2020 23:25:47.225  [CHRONO] TCalculator.Divide -> Divide 10 / 2 = 1,50s

當進入和退出函式時獲取通知,並計算時間:

function TCalculator.Mult(a, b: Int64): Int64;
begin
  {$IFDEF DEBUG}
  TDebugger.Enter(Self, 'Mult').TimeIt;
  {$ENDIF}
  Result := a * b;
  // 模擬工作2秒
  Sleep(2000);
end;
// 返回:
// 29-06-2020 22:58:45.808  [ENTER] >> TCalculator.Mult
// 29-06-2020 22:58:47.810  [EXIT] >> TCalculator.Mult in 2,00s

Quick.Parameters:

使用命令列擴充套件,可以輕鬆處理命令列引數。
定義一個從TParameters或TServiceParameters(如果使用QuickAppServices)繼承的類,將可能的引數作為已釋出的屬性:

uses
  Quick.Parameters;
type
  TCommand = (Copy, Move, Remove);
  TMyMode = (mdAdd, mdSelect, mdRemove);

  [CommandDescription('使用Quick.Parameters的簡單控制檯應用程式示例')]
  TMyParameter = class(TParameters)
  private
    // ... [私有成員]
  published
    // ... [已釋出的屬性]
  end;

使用引數:

params := TMyParameter.Create;

當您使用--help呼叫exe時,將獲得文件。如果需要檢查開關或值,可以這樣做:

if params.Port = 0 then ...
if params.Silent then ...

QuickParameters使用自定義屬性來定義特殊的引數條件:

  • CommandDescription: 定義在幫助文件中描述您的應用程式的文字。
  • ParamCommand(number): 為單個引數定義命令列中的靜態位置。
  • ParamName(name,alias): 為引數定義不同的名稱。允許使用類屬性中不允許的特殊字元(如檔名或config.file)。可選的Alias引數定義了替代(通常是短名稱)引數名稱。
  • ParamHelp(helptext,valuename): 在用法部分定義命令列幫助文字和值名稱。
  • ParamSwitchChar(sign): 定義指示開關或引數的字串或字元。如果沒有定義,將預設使用雙破折號(--)。
  • ParamValueSeparator(sign): 定義從值(filename=config.json)中分離引數名稱的字串或字元。如果沒有定義,將預設使用等號(=)。
  • ParamValueIsNextParam: 定義沒有值分隔符的引數值(filename c:\config.ini)。
  • ParamRequired: 定義引數為必需。如果未找到引數,將引發異常。

QuickParameter會自動檢查值型別。如果將引數值定義為Integer,並傳遞了字母數字值,將引發異常。

幫助定製:
您可以使用ColorizeHelp定義自己的顏色定製。如果Enabled屬性為True,則使用自定義顏色,否則使用黑白顏色。

Parameters.ColorizeHelp.Enabled := True;
Parameters.ColorizeHelp.CommandName := ccCyan;
Parameters.ColorizeHelp.CommandUsage := ccBlue;

當引數檢測到幫助引數時,將顯示幫助文件。

Parameters.ShowHelp: 顯示自動生成的幫助文件。

Quick.Url.Utils:

  • GetProtocol: 從URL中獲取協議。
  • GetHost: 從URL中獲取主機名。
  • GetPath: 從URL中獲取路徑。
  • GetQuery: 從URL中獲取查詢部分。
  • RemoveProtocol: 從URL中移除協議。
  • RemoveQuery: 從URL中移除查詢部分。
  • EncodeUrl: 對URL中的路徑和查詢部分進行編碼。

Quick.RegEx.Utils:

常用驗證工具。
(此部分未給出具體示例程式碼)

Quick.Conditions:

以流暢風格進行前置條件和後置條件的驗證。
Condition.Requires在執行某些操作之前評估變數的條件。
Condition.Ensures在執行某些操作之後評估變數結果的條件。

Condition.Requires(num, "num")
    .IsInRange(1, 10, 'value for num is out of range');   // 如果不在範圍內,則丟擲自定義錯誤
    .IsNotGreater(50);   // 如果不等於50,則丟擲ArgumentException

Condition.Requires(myobj, "myobj")
    .WithExceptionOnFailure(EMyException) // 如果失敗,則丟擲特定異常
    .IsNotNull();          // 如果為null,則丟擲ArgumentNullException
    .Evaluate(myobj.id > 10); // myobj.id必須大於10

Condition.Requires(text, "text")
    .IsNotEmpty();          // 如果為空,則丟擲ArgumentNullException
    .StartsWith("<html>") // 如果不以<html>開頭,則丟擲ArgumentException
    .EndsWith("</html>") // 如果不以</html>結尾,則丟擲ArgumentException
    .IsNotLowerCase; // 如果不是小寫,則丟擲ArgumentException
    .Evaluate(text.Contains("sometxt") or text.Contains('othertxt')); // 如果不滿足條件,則丟擲ArgumentException

hieroly 翻譯整理於 2024年5月12日

你想學習Delphi或提高你的技能嗎?訪問 learndelphi.org