Quick Library 簡介

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('[email protected]','[email protected]','Email subject','My message body');// 您可以定義更高級的選項
SMTP.SenderName := 'John';
SMTP.From := '[email protected]';
SMTP.Recipient := '[email protected],[email protected]';
SMTP.Subject := 'Email subject';
SMTP.AddBodyFromFile := '.\body.html';
SMTP.CC := '[email protected]';
SMTP.BCC := '[email protected]';
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僅允許緩存定義的類型。

  • 創建:可以定義清除間隔、序列化和壓縮引擎。默認情況下,它使用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實例將由代碼銷燬。

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註冊它以使其可注入到構造函數方法中。

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 / IList:允許使用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 / IObjectList:允許使用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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章