正文 昨天玩到了凌晨 3 點,今天睡了一天…… 斷斷續續睡到 12 點起床,下午又從 5 點睡到了 7 點。我願稱之為睡神……. 其它時間就是做工作日一直沒時間做的雜事,比如洗衣服,刷鞋,換洗被套什麼的,還挺花時間。用了得有兩三個小時。 所以昨天說的今天開擺,那是真的開擺了 (笑。 現在晃一下頭,能 ...
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