Quick Library 簡介

来源:https://www.cnblogs.com/hieroly/p/18185987
-Advertisement-
Play Games

正文 昨天玩到了凌晨 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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • theme: condensed-night-purple highlight: androidstudio 主從複製原理 建立連接 從節點在配置了 replicaof 配置了主節點的ip和port 從庫執行replicaof 併發送psync命令 同步數據到從庫 主庫bgsave生成RDB文件,並 ...
  • Java Chassis 3通過介面維度負載均衡的策略設置,為不同的應用場景提供了非常強大的負載均衡管理能力,幫助解決負載不均衡、會話粘滯等應用負載問題。 ...
  • 通過本文,我們深入瞭解了 Django 框架的一些基本概念和使用方法,以及如何利用 Django 構建一個簡單的圖像上傳應用程式。從項目創建到環境配置,再到 admin 端圖像處理和用戶圖片上傳,我們逐步學習瞭如何利用 Django 提供的功能快速搭建 Web 應用。無論是對於初學者還是有一定經驗的... ...
  • 運算符與表達式 Created: November 29, 2023 10:38 PM 運算符 運算符 釋義 +、-、*、/ 略 **、//、% 乘方、整除(向下取整至最接近的整數、餘數 <<、>> 指的是二進位左右移 &按位與 按位與是針對二進位數的操作,指將兩個二進位數的每一位都進行比較,如果兩 ...
  • 在現代社會中,機動車已經成為人們生活的重要交通工具。而行駛證作為機動車的身份證明,具有重要的法律效力。然而,對於行駛證上的信息進行手工識別是一項繁瑣的工作,容易出現錯誤,並且耗時較長。為瞭解決這個問題,挖數據平臺提供了行駛證OCR識別Api介面,可以對行駛證上的信息進行快速準確地識別和提取。 這個A ...
  • 大家好,我是 Java陳序員。 問君能有幾多愁,開源項目解千愁! 今天,給大家介紹一個快速開發平臺,完全開源可商用! 關註微信公眾號:【Java陳序員】,獲取開源項目分享、AI副業分享、超200本經典電腦電子書籍等。 項目介紹 SmartAdmin —— 一個簡潔、高效、安全的快速開發平臺,以高質 ...
  • 大家好,我是R哥。 金三銀四結束了,上個月分享了一個 35K 入職的面試輔導案例: 35K*14 薪入職了,這公司只要不裁員,我能一直呆下去。。 今天再分享一個上個月讓人很有成就感的面試輔導 case: 外包、空窗四個月、薪資 10k、996 ——> 甲方公司、薪資15k、早九晚六(WLB),從報名 ...
  • 當一個線程被啟動後,如果再次調start()方法,將會拋出IllegalThreadStateException異常。 這是因為Java線程的生命周期只有一次。調用start()方法會導致系統在新線程中運行執行體,但是如果線程已經結束,則不能再次使用,需要重新創建一個新的線程對象並調用start()... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...