
QuickLib เป็น Delphi/Firemonkey (Windows, Linux, Android, OSX & IOS) และ FPC (Windows & Linux) ไลบรารีที่มีฟังก์ชั่นที่น่าสนใจและรวดเร็วในการใช้งานสร้างขึ้นเพื่อลดความซับซ้อนของการพัฒนาแอปพลิเคชันและการสนับสนุน crossplatform Delphi XE8 - Delphi 12 เอเธนส์สนับสนุน
ได้โปรด "Star" โครงการนี้ใน GitHub! ไม่มีค่าใช้จ่ายใด ๆ นอกจากช่วยอ้างอิงรหัส 
หากคุณพบว่าโครงการนี้มีประโยชน์โปรดพิจารณาบริจาค
พื้นที่ของฟังก์ชั่น:
คำอธิบายหน่วยหลัก:
อัปเดต:
อนุญาตให้แอพคอนโซลเรียกใช้เป็นโหมดคอนโซลหรือโหมดบริการที่มีรหัสการดีบักง่ายๆ
if not AppService.IsRunningAsService then
begin
...your code running as console
end
else
begin
AppService.ServiceName := ' MyService ' ;
AppService.DisplayName := ' MyServicesvc ' ;
// you can pass an anonymous method to events
AppService.OnStart := procedure
begin
...your start code
end ;
AppService.OnExecute := YourExecuteFunction;
AppService.OnStop := YourStopFunction;
AppService.CheckParams;
end ;ลดความซับซ้อนของการวนซ้ำด้วย Azure และ Amazon Cloud Storage
// connect to a Azure blobstorage
QuickAzure := TQuickAzure.Create(AzureAccountName,AzureAccountKey);
// download a blob file to a stream
done := QuickAzure.GetBlob( ' MyContainer ' , ' MyFile.jpg ' ,ResponseInfo,MyStream);
// check if exists a folder
found := ExistFolder( ' MyContainer ' , ' /Public/Documents/Personal ' );
// list blobs starting with a pattern (recursively or not)
for azBlob in ListBlobs( ' MyContainer ' , ' /Public/Documents ' ,Recursive,ResponseInfo) do
begin
if azBlob.Size > 1000 then Showmessage(azBlob. Name );
end ;ฟังก์ชั่น CIDR และ IP
// convert ip string to integer
IPv4ToInt( ' 192.168.1.10 ' );
// get first and last ip of a subnet scope
GetIpRange( ' 192.168.100.0 ' , ' 255.255.255.0 ' ,LowIp,HighIP);ฟังก์ชั่นที่จำเป็นบ่อยครั้งในชีวิตประจำวันของนักพัฒนา
// coverts UTC time TDateTime to Local date time
UTCToLocalTime(MyUTCTime);
// generate a 10 char length random password with alfanumeric and signs.
RandomPassword( 10 ,[pfIncludeNumbers,pfIncludeSigns]);
// Capitalize every word of a phrase
CapitalizeAll( ' the grey fox ' ); // returns "The Grey Fox"
// Simple TCounter and TTimeCounter for loops
counter := TCounter;
counter.Init( 200 );
timecounter : TTimeCounter;
timecounter.Init( 10000 );
while true do
begin
Inc(n);
{ your procedural process here }
// every 200 steps writes to console
if counter.Check then writeln(Format( ' Processed %d entries ' ,[n]));
// every 10 seconds writes to console
if timecounter.Check then writeln( ' Im working... ' );
end ;Chronometer และเกณฑ์มาตรฐานชิ้นส่วนของรหัสนั้นง่าย
// get elapsed time execution of a code part
Chrono := TChronometer.Create(False);
Chrono.Start;
...code you need benchmark
Chrono.Stop;
// shows elapsed time in LongTime format (2 hour(s) and 10 minute(s))
Showmessage(Chrono.TimeElapsed(True));
// shows elapsed time in ShortTime format (02:10:00)
Showmessage(Chrono.TimeElapsed(False));
// get benchmak info of a process
Chrono := TChronoBenchMark.Create;
Chrono.TotalProcess := 100000 ;
for i := 1 to 10000 do
begin
{ your process here }
Chrono.CurrentProcess := i;
// shows estimated time your process will take in x hour(s), x minute(s) x second(s) format
writeln(Chrono.EstimatedTime(True));
// shows speed: num items per second processed of your process
writeln(Format( ' Items processed %d/sec ' ,[Chrono.Speed]));
end ;
writeln(Chrono.ElapsedTime(False)); // shows total time elapsed in 00:00:00 format เขียนข้อความบันทึกเพื่อคอนโซลด้วยสีและอื่น ๆ ...
// define which level of output needed
Console.Verbose := LOG_DEBUG;
// writes line to console in red color
cout( ' Error x ' ,etError);
// writes formatted line in green color
coutFmt( ' Proccess %s finished ' ,[ProccesName],etSuccess);
// writes integer
cout( 12348 );
// Connect a QuickLog and write to disk and screen with one line of code (with independent verbose levels)
MyQuickLog := TQuickLog.Create;
MyQuickLog.Verbose := LOG_ALL;
Console.Verbose := LOG_ONLYERRORS;
Console.Log := MyQuickLog;เข้าสู่ดิสก์หรือหน่วยความจำด้วยระดับ verbose และการหมุนอวกาศรายวันหรือสูงสุด
// write a header on start with info as running path, appname, debugmode, user, etc...
Log.ShowHeader := True;
// sets log with rotation at 20MB
Log.SetLog( ' .mylog.log ' ,False, 20 );
// write an error message
Log.Add( ' Error x ' ,etError);
// write formatted error message
Log.Add( ' Error is %s ' ,[ErrorStr],etError);โหลด/บันทึกการกำหนดค่าเป็นไฟล์ JSON หรือ YAML หรือคีย์รีจิสทรี Windows สร้างคลาส Descend จาก TappConfigjson, Tappconfigyaml หรือ TappConfigregistry และเพิ่มคุณสมบัติที่เผยแพร่จะถูกโหลด/บันทึก การกำหนดค่าไฟล์สามารถโหลดซ้ำในการตรวจจับการเปลี่ยนแปลงไฟล์
// create a class heritage
TMyConfig = class (TAppConfigJson)
private
fName : string;
fSurname : string;
fStatus : Integer;
published
property Name : string read fName write fName;
property SurName : string read fSurname write fSurname;
property Status : Integer read fStatus write fStatus;
end ;
// create your config to json file
// Add Quick.Config.Json to your uses
MyConfig := TMyConfig.Create( ' Config.json ' );
MyConfig.Provider.CreateIfNotExists := True;
MyConfig.Provider.ReloadIfFileModified := True;
MyConfig. Name := ' John ' ;
MyConfig.Surname := ' Smith ' ;
// load
MyConfig.Load;
// save
MyConfig.Save;
// create your config to Windows Registry
// Add Quick.Config.Registry to your uses
MyConfig := TMyConfig.Create;
// Define Registry as HKEY_CURRENT_USERSoftwareMyApp
MyConfig.HRoot := HKEY_CURRENT_USER;
MyConfig.MainKey := ' MyApp ' ;
MyConfig. Name := ' John ' ;
MyConfig.Surname := ' Smith ' ;
// load
MyConfig.Load;
// save
MyConfig.Save;
// Create a custom Config with no default provider
TMyConfig = class (TAppConfig)
...your properties
end ;
MyConfig := TMyConfig.Create(TAppConfigJsonProvider.Create( ' .config.json ' );
ตรวจสอบไฟล์สำหรับการเปลี่ยนแปลงและโยนเหตุการณ์
FileMonitor.Filename := ' .myfile.txt ' ;
// check file changes every 2 seconds
FileMonitor.Interval := 2000 ;
// watch for deleted or modified file events
FileMonitor.Notifies := [mnFileModified, mnFileDeleted)];
FileMonitor.OnFileChange := MyFileChangeFunction;
FileMonitor.Enabled := True;ใช้สำหรับการทำงานกับวัตถุ JSON
// When unit declared in uses, a TObject Helper allows all your objects to be loaded or saved to/from json string
MyObject.FromJson := jsonstring;
MyString := MyObject.ToJson;
// You can clone simple objects with clone function
MyObject1.Clone(MyObject2);ส่งอีเมลด้วยรหัสสองบรรทัด
// Send email
SMTP := TSMTP.Create( ' mail.domain.com ' , 25 ,False);
SMTP.SendMail( ' [email protected] ' , ' [email protected] ' , ' Email subject ' , ' My message body ' );
// You can define more advanced options
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;เธรดชั้นเรียนที่ปลอดภัย
TTHREADEDQUEUCS: เวอร์ชันของ TTHREADEQUEUE กับส่วนที่สำคัญ
TTHREADOBJECTLIST: รายการวัตถุที่ปลอดภัยเธรด
TTHREADEQUEUELIST: รายการคิวปลอดภัยเธรด autogrow และกับส่วนที่สำคัญ
Tanonymoustread: สร้างเธรดที่ไม่ระบุชื่อที่กำหนดวิธีการทำงานที่ไม่ได้รับการตรวจสอบและการยกเลิก ใช้วิธีการ EXECUTE_SYNC และ ONDERTEMINATE_SYNC หากรหัสจำเป็นต้องอัปเดต UI
// simple anonymousthread
TAnonymousThread.Execute(
procedure
var
i : Integer;
begin
for i := 0 to 10 do cout( ' Working %d ' ,[i],etTrace);
cout( ' executed thread ' ,etSuccess);
end )
.OnTerminate(
procedure
begin
cout( ' terminated thread ' ,etSuccess);
cout( ' PRESS <ENTER> TO EXIT ' ,etInfo);
end )
.Start;Truntask: เปิดเธรดงานเดียวอัตโนมัติพร้อมนโยบายการควบคุมความผิดพลาดและการลองใหม่ พารามิเตอร์สามารถส่งผ่านและสร้างลงในรหัส
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;TBACKGROYSTSKS: เปิดงานในพื้นหลังทำให้จำนวนคนงานพร้อมกันที่มีนโยบายการควบคุมความผิดพลาดและการลองใหม่ ใช้วิธีการ addtask_sync และ ontermate_sync หากรหัสจำเป็นต้องอัปเดต UI
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: ทางเลือกในการจับเวลา คุณสามารถกำหนดงานที่มีเวลาเริ่มต้นตัวเลือกทำซ้ำและวันหมดอายุและนโยบายการควบคุมล้มเหลวและลองอีกครั้ง ใช้ addtask_sync, onterminate_sync และ onexpired_sync หากรหัสจำเป็นต้องอัปเดต UI คุณสามารถกำหนดวิธีการที่ไม่ระบุชื่อเพื่อดำเนินการยกเว้นการยุติและเหตุการณ์หมดอายุ
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;จัดการนโยบายที่ล้มเหลวและลองใหม่การกำหนดการลองใหม่สูงสุดรอเวลาพักระหว่างการลองใหม่และการแบ่งวงจร mecanism
จัดการกระบวนการของ Windows
// kill explorer process
KillProcess( ' explorer.exe ' );
// determine if an application is running
if IsProcessRunning( ' explorer.exe ' ) then Showmessage( ' Explorer is running! ' );
// get username who is running an exe
writeln( ' Explorer.exe open by: ' + GetProcessUser( ' explorer.exe ' );
// gets handle of a window with a 20 seconds timeout
if FindWindowTimeout( ' MainWindow ' , 20 ) then writeln( ' Window detected ' );จัดการบริการ Windows
// detect if a service is installed
if not ServiceIsPresent( ' localhost ' , ' MySvc ' ) then raise Exception.Create( ' Service not installed! ' );
// Start a service
ServiceStart( ' localhost ' , ' MySvc ' );
// Uninstall a service
ServiceUninstall( ' MySvc ' );รูปแบบสตริง
// Format bytes to MB, GB, TB...
FormatBytes( 50000 ) // shows 50KB
FormatBytes( 90000000 ) // shows 90MB ทำให้เป็นอนุกรมวัตถุจาก/ถึง JSON TEXT คุณสามารถกำหนดได้ว่าจะดำเนินการสาธารณะหรือเผยแพร่ (เฉพาะ Delphi, FPC RTTI รองรับคุณสมบัติที่เผยแพร่เท่านั้น)
json := ' {"name":"Peter","age":30} ' ;
serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
try
serializer.JsonToObject(user,json);
finally
serializer.Free;
end ;ฟิลด์แผนที่จากคลาสหนึ่งไปยังชั้นเรียนอื่น อนุญาตให้แมปแบบกำหนดเองตรงกับฟิลด์ที่แตกต่างกันและขั้นตอนการแมปแบบกำหนดเองเพื่อ CAST/แปลงฟิลด์ด้วยตนเอง
// Map values from User1 to User2
TMapper<TUser2>.Map(User);
// Map custom mappings
AutoMapper := TAutoMapper<TUser,TUser2>.Create;
// option1: you can define auto map different named properties
AutoMapper.CustomMapping.AddMap( ' Cash ' , ' Money ' );
AutoMapper.CustomMapping.AddMap( ' Id ' , ' IdUser ' );
// option2: you can decide to modify each property manually or allow to auto someones
AutoMapper.OnDoMapping := procedure( const aSrcObj : TUser; const aTargetName : string; out Value : TFlexValue)
begin
if aTargetName = ' Money ' then Value := aSrcObj.Cash * 2
else if aTargetName = ' IdUser ' then Value := aSrcObj.Id;
end ;
// option3: you can modify some properties after automapping done
AutoMapper.OnAfterMapping := procedure( const aSrcObj : TUser; aTgtObj : TUser2)
begin
aTgtObj.Money := aSrcObj.Cash * 2 ;
aTgtObj.IdUser := aSrcObj.Id;
end ;
User2 := AutoMapper.Map(User);ใช้เป็นคลาส 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;
// show as json string
Writeln(user.ToJson);
// mapping to other class
user.Mapto(User2);
Writeln(user2.ToJson);
// load from file
user.LoadFromFile( ' .user.json ' );
// save to file
user2.SaveToFile( ' .user2.json ' );
end ;ปรับปรุงรายการด้วยคุณสมบัติการจัดทำดัชนีหรือการค้นหา
var
users : TIndexedObjectList<TUser>;
begin
users := TIndexedObjectList<TUser>.Create(True);
// create index by property "Name"
users.Indexes.Add( ' Name ' , ' Name ' ,TClassField.cfProperty);
// create index by private field "Id"
users.Indexes.Add( ' Id ' , ' fId ' ,TClassField.cfField);
// get user by "Name" index
writeln(users.Get( ' Name ' , ' Peter ' ).SurName);
end ;FlexValue จัดเก็บชนิดข้อมูลใด ๆ และอนุญาตให้ส่งผ่านไปยังคลาสอื่น ๆ ด้วยตัวดำเนินการในตัวและระบบอัตโนมัติ
var
value : TFlexValue;
str : string;
num : Integer;
begin
value := ' hello ' ;
str := value ;
value := 123 ;
num := value ;
end ;อาร์เรย์ที่ดีขึ้น
txarray: อาร์เรย์ด้วยวิธีการเช่น tlist
var
users : TXArray<TUser>;
begin
users.Add(User);
if users.Count:= TIndexedObjectList<TUser>.Create(True);
// create index by property "Name"
users.Indexes.Add( ' Name ' , ' Name ' ,TClassField.cfProperty);
// create index by private field "Id"
users.Indexes.Add( ' Id ' , ' fId ' ,TClassField.cfField);
// get user by "Name" index
writeln(users.Get( ' Name ' , ' Peter ' ).SurName);
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 ;โครงสร้างวัตถุ Yaml
Tyamlobject: วัตถุ Yaml คือและอาร์เรย์ของคู่ yamlvalue
// create Yaml object from yaml text
yamlobj.ParseYamlValue(aYaml)
// add a pair
yamlobj.AddPair( ' Name ' , ' Mike ' );
// display as yaml structure
Writeln(yamlobj.ToYaml);Tyamlarray: อาร์เรย์ของวัตถุหรือสเกลาร์
yamlarray.AddElement(TYamlPair.Create( ' Age ' , 30 ));
yamlobj.AddPair( ' myarray ' ,yamlarray);Tyamlpair: คู่ชื่อคู่ ค่าสามารถเป็นวัตถุอาร์เรย์หรือสเกลาร์
n := yamlobj.GetPair( ' Name ' ). Value as TYamlInteger;serialize/deserialize วัตถุจาก/ถึง yaml
// Serialize
text := YamlSerializer.ObjectToYaml(obj);
// Deserialize
YamlSerializer.YamlToObject(obj,yamltext);ประเมินคุณสมบัติของวัตถุหรือค่าเดียวโดยใช้นิพจน์
if TExpressionParser.Validate(user,( ' (Age > 30) AND (Dept.Name = "Financial") ' ) then
begin
// do something
end ;
if TExpressionParser.Validate(user,( ' (20 > 30) OR (5 > 3) ' ) then
begin
// do something
end ;ทำให้การสืบค้น LINQ ไปยัง TobjectList, Tlist, Tarray และ TxArray, ดำเนินการ Select โดย Complex ซึ่งเป็นไวยากรณ์ SQL, อัปเดตและสั่งซื้อผ่านรายการของคุณ ที่ประโยคใช้เนมสเปซเพื่อกำหนดคุณสมบัติซ้อนกัน LINQ สามารถค้นหาองค์ประกอบลงในอาร์เรย์คุณสมบัติ ตอนนี้รวมและ Tarray Helper เพื่อเพิ่มลบและค้นหาด้วยนิพจน์ปกติลงในอาร์เรย์
// Select multi conditional
for user in TLinq<TUser>.From(userslist).Where( ' (Name = ?) OR (SurName = ?) OR (SurName = ?) ' ,[ ' Peter ' , ' Smith ' , ' Huan ' ]).Select do
begin
// do something
end ;
// Select like and update field
TLinq<TUser>.From(userlist).Where( ' SurName Like ? ' ,[ ' %son ' ]).SelectFirst. Name := ' Robert ' ;
// Select top and Order by field
for user in TLinq<TUser>.From(userlist).Where( ' Age > ? ' ,[ 18 ]).SelectTop( 10 ).OrderBy( ' Name ' ) do
begin
// do something
end ;
// update fields by conditional
TLinq<TUser>.From(userlist).Where( ' Name = ? ' ,[ ' Peter ' ]).Update([ ' Name ' ],[ ' Joe ' ]);
// count results
numusers := TLinq<TUser>.From(userlist).Where( ' (Age > ?) AND (Age < ?) ' ,[ 30 , 40 ]).Count;TCUSTOMHTTPSERVER เป็น HTTPSERVER ที่เชื่อมต่ออย่างง่ายด้วยการใช้งาน HTTPREQUEST และ HTTPRESSPONSE ของตัวเองเพื่อให้การเปลี่ยนแปลงของเอ็นจิ้น 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 ;แคชวัตถุหรือสตริงที่มีเวลาหมดอายุเพื่อหลีกเลี่ยงการสร้างข้อมูลนี้ทุกครั้งจำเป็นต้องใช้ (แบบสอบถามฐานข้อมูลยากที่จะคำนวณข้อมูล ฯลฯ ) TMemoryCache อนุญาตให้แคชวัตถุและสตริง TMEMORYCACHE เวอร์ชันทั่วไปอนุญาตให้แคชประเภทที่กำหนดไว้เท่านั้น
// create MemoryCache with 10 seconds purge interval
cache := TMemoryCache.Create( 10 );
// create MemoryCache for a type
cache := TMemoryCache<TMyObj>.Create; // set string to cache without expiration
cache.SetValue( ' mystring ' , ' hello world ' );
// set string to cache with expiration to 10 seconds
cache.SetValue( ' mystring ' , ' this cache will expire in 10 seconds ' ;
// set object to cache
cache.SetValue( ' Obj1 ' ,valueobj); // get string query result
cache.GetValue( ' Query12 ' );
// get integer
cache.TryGetValue<Integer>( ' number ' ,valueint);
// get object
cache.TryGetValue( ' Obj1 ' ,valueobj);RemoveValue: ลบวัตถุออกจากแคช
ผู้ให้บริการเครื่องยนต์แคช:
tcacheserializerjson: ใช้ JSON เพื่อทำให้เป็นอนุกรมข้อมูลแคช
TCacheComPressorGZIP: ใช้ GZIP เพื่อบีบอัดข้อมูลแคช
TCacheComPressorlzo: ใช้ LZO เพื่อบีบอัดข้อมูลแคช
// create MemoryCache with 20 seconds purge interval and compression with LZO engine
cache := TMemoryCache.Create( 10 , nil ,TCacheCompressorLZO.Create);การผกผันของตัวจัดการการควบคุมช่วยให้ Outocreate เชื่อมต่อ Object O หรือ autoInject ในคลาสคอนสตรัคเตอร์เพื่อหลีกเลี่ยงการพึ่งพา
สร้างคอนเทนเนอร์เพื่อจัดการการฉีดพึ่งพา
iocContainer := TIocContainer.Create;ประเภทลงทะเบียน:
คุณต้องลงทะเบียนประเภทก่อนที่คุณจะสามารถฉีดได้ ประเภทสามารถลงทะเบียนเป็นซิงเกิลตันชั่วคราว Singleton : วงจรชีวิตจะเป็นหนึ่งเดียวสำหรับการฉีดทั้งหมดคล้ายกับตัวแปรทั่วโลก ชั่วคราว : วัฏจักรชีวิตจะเป็นหนึ่งอินสแตนซ์ต่อการฉีดแต่ละครั้ง ลงทะเบียนประเภทอินเตอร์เฟสลงในคอนเทนเนอร์เป็นชั่วคราว:
iocContainer.RegisterType<IMultService,TMultService>.AsTransient;ลงทะเบียนประเภทอินเทอร์เฟซเป็นซิงเกิลตันการสร้างการก่อสร้าง:
iocContainer.RegisterType<ISumService,TSumService>.AsSingleTon.DelegateTo(
function : TSumService
begin
Result := TSumService.Create;
end
);ลงทะเบียนอินสแตนซ์:
ลงทะเบียนวัตถุอินสแตนซ์ที่มีชื่อเป็นชั่วคราวการก่อสร้างที่ได้รับมอบหมาย:
iocContainer.RegisterInstance<TDivideService>( ' one ' ).AsTransient.DelegateTo(
function : TDivideService
begin
Result := TDivideService.Create(True);
end
);ตัวเลือกการลงทะเบียน:
ลงทะเบียน ioptions (Singleton เท่านั้น):
iocContainer.RegisterOptions<TMyOptions>(MyOptions);แก้ไขประเภท:
AbtractFactory: สร้างคลาสที่พยายามแก้ไขพารามิเตอร์วิธีการสร้างทั้งหมดด้วยการฉีดพึ่งพา
MyClass := iocContainer.AbstractFactory<TMyBaseClass>(TMyClass);แก้ไขการพึ่งพาอินเตอร์เฟส:
multservice := iocContainer.Resolve<IMultService>;
result := multservice.Mult( 2 , 4 );แก้ไขอินสแตนซ์:
แก้ไขการพึ่งพาอินสแตนซ์ชื่อ:
divideservice := iocContainer.Resolve<TDivideService>( ' other ' );
result := divideservice.Divide( 100 , 2 );อินเทอร์เฟซอินสแตนซ์จะได้รับการปลดปล่อยโดยอัตโนมัติ แต่การพึ่งพาอินสแตนซ์จะได้รับการปลดปล่อยหากกำหนดเป็นซิงเกิลตันอินสแตนซ์ชั่วคราวจะถูกทำลายด้วยรหัส
คุณกำหนดส่วนเป็นคลาสและบันทึกเป็นการตั้งค่าไฟล์เดียว ทำงานคล้ายกับตัวเลือก Dotnet ไฟล์ตัวเลือกสามารถอยู่ในรูปแบบ 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 ของคุณ
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>;
LoggginOptions.Path := ' C:Path ' ;ใช้ ioptions: IOptions เป็นอินเทอร์เฟซแบบฉีดพึ่งพากับ toptions คุณสามารถลงทะเบียนกับ IOCContainer.RegisterOptions เพื่อฉีดเข้าไปในวิธีการสร้าง
UIOptions := Options.GetSectionInterface<TUIOptions>. Value ;
UIOptions.WindowColor := clBlue;โหลด/บันทึกตัวเลือก:
โหลดตัวเลือกจากการตั้งค่าไฟล์:
options.Load;บันทึกตัวเลือกลงในการตั้งค่าไฟล์:
options.Save;หากคุณกำหนดการสร้างคอนเทนเนอร์ด้วยพารามิเตอร์ reloadonChanged เป็นจริงการตั้งค่าไฟล์ทุกครั้งจะเปลี่ยนการกำหนดค่าจะถูกโหลดใหม่ หากคุณต้องการควบคุมเมื่อโหลดซ้ำคุณสามารถฟังเหตุการณ์:
Options.OnFileModified := procedure
begin
cout('Detected config file modification!',etWarning);
end;
กำหนดพูลของการเชื่อมต่อเธรดหรือวัตถุใด ๆ ที่คุณต้องการควบคุมเพื่อหลีกเลี่ยงการใช้ทรัพยากรเช่นการเชื่อมต่อฐานข้อมูลไคลเอนต์ HTTP ฯลฯ ...
สร้างกลุ่มไคลเอนต์ HTTP:
pool := TObjectPool<THTTPClient>.Create( 5 , 5000 ,procedure( var aInstance : THTTPClient)
begin
aInstance := THTTPClient.Create;
aInstante.UserAgent := ' MyAgent ' ;
end );รับวัตถุจากพูล:
httpcli := pool.Get.Item;
statuscode := httpcli.Get( ' https://www.mydomain.com ' ).StatusCode;กำหนดรายการที่เชื่อมต่อและ ObjectList ด้วยการสนับสนุน LINQ ที่สืบทอดมา
myarray := [ ' Joe ' , ' Mat ' , ' Lee ' ];
// search for regex match
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 ;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 เพื่อดูฟังก์ชั่นเพิ่มเติมที่อนุญาต
เทมเพลตสตริงการแทนที่โดยใช้ฟังก์ชันพจนานุกรมหรือตัวแทน คุณสามารถระบุตัวอักษรโทเค็นที่ยกมาได้
แทนที่พจนานุกรม:
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 token = ' User ' then Result := ' John '
else if token = ' Surname ' then Result := ' Peterson '
else if token = ' Age ' then Result := ' 20 ' ;
end );
Result := template.Replace(mytemplate);Debug ใช้เพื่อตรวจสอบประสิทธิภาพและรับจุดตรวจสอบ Method และออกกำหนดด้วยการดีบักคำสั่งคอมไพเลอร์ให้ใช้งานเฉพาะเมื่อแอปของคุณรวบรวมในโหมดดีบัก บนแอพคอนโซลใช้คอนโซลตามค่าเริ่มต้น คุณสามารถส่งเครื่องบันทึกเพื่อส่งออกใน:
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;
// simulate working for 200ms
Sleep( 200 );
end ;
// Returns:
// 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;
// simulate working for 1 seconds
Sleep( 1000 );
end ;
// Returns:
// 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;
// simulate working for 500ms
Sleep( 500 );
{ $IFDEF DEBUG }
crono.BreakPoint( ' Only divide ' );
{ $ENDIF }
// simulate working for 1 second
Sleep( 1000 );
{ $IFDEF DEBUG }
crono.BreakPoint( ' Only Sleep ' );
{ $ENDIF }
end ;
// Returns:
// 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;
// simulate working for 2 seconds
Sleep( 2000 );
end ;
// Returns:
// 29-06-2020 22:58:45.808 [ENTER] >> TCalculator.Mult
// 29-06-2020 22:58:47.810 [EXIT] >> TCalculator.Mult in 2,00s การทำงานกับพารามิเตอร์ CommandLine จะง่ายโดยใช้ส่วนขยาย CommandLine กำหนดคลาสที่สืบทอดมาจาก tparameters หรือ tserviceParameters (หากทำงานกับ QuickAppServices) พร้อมข้อโต้แย้งที่เป็นไปได้ของคุณเป็นคุณสมบัติที่เผยแพร่:
uses
Quick.Parameters;
type
TCommand = (Copy, Move, Remove);
TMyMode = (mdAdd, mdSelect, mdRemove);
[CommandDescription( ' Simple console application example with Quick.Parameters ' )]
TMyParameter = class (TParameters)
private
fCommand : TCommand;
fHost : string;
fPort : Integer;
fRetries : Integer;
fUseTCP : Boolean;
fConfigFile: string;
fSilent: Boolean;
fMyMode: TMyMode;
fLogErrorsConsole: Boolean;
fLogErrors: Boolean;
fShowReport: Boolean;
published
[ParamCommand( 1 )]
[ParamRequired]
[ParamHelp( ' Command action. ' , ' command-action ' )]
property Command : TCommand read fCommand write fCommand;
[ParamName( ' HostName ' ),ParamRequired]
[ParamHelp( ' Define host to connect. ' , ' host ' )]
property Host : string read fHost write fHost;
[ParamName( ' Port ' , ' p ' )]
[ParamValueIsNextParam]
[ParamHelp( ' Define Port to connect (default 80) ' , ' port ' )]
property Port : Integer read fPort write fPort;
[ParamHelp( ' Number of max retries. ' )]
property Retries : Integer read fRetries write fRetries;
[ParamHelp( ' Path to config. ' , ' path ' )]
[ParamName( ' Config-file ' )]
property ConfigFile : String read fConfigFile write fConfigFile;
[ParamHelp( ' Silent mode. ' )]
property Silent : Boolean read fSilent write fSilent;
[ParamHelp( ' Modes (mdAdd, mdSelect, mdRemove) ' )]
property Mode : TMyMode read fMyMode write fMyMode;
end ;
ใช้ param:
params := TMyParameter.Create;เมื่อคุณโทรหา exe ของคุณด้วย -ช่วยเหลือคุณจะได้รับเอกสาร หากคุณต้องการตรวจสอบสวิตช์หรือค่าคุณสามารถทำได้เช่นนี้:
if params.Port = 0 then ...
if params.Silent then ...QuickParameters ใช้แอตทริบิวต์ที่กำหนดเองเพื่อกำหนดเงื่อนไขพารามิเตอร์พิเศษ:
CommandDescription: กำหนดข้อความเพื่ออธิบายแอปพลิเคชันของคุณในเอกสารช่วยเหลือ
ParamCommand (หมายเลข): กำหนดตำแหน่งคงที่เป็นคำสั่งสำหรับพารามิเตอร์เดียว
paramname (ชื่อนามแฝง): กำหนดชื่อที่แตกต่างกันสำหรับพารามิเตอร์ อนุญาตให้ใช้อักขระพิเศษที่ไม่อนุญาตให้ใช้คุณสมบัติคลาส (เช่น file-name หรือ config.file) อาร์กิวเมนต์นามแฝงทางเลือกกำหนดชื่อพารามิเตอร์ทางเลือก (ชื่อสั้น ๆ )
ParamHelp (Helptext, ValuEname): กำหนดชื่อข้อความช่วยเหลือและชื่อค่าใช้จ่ายในส่วนในส่วนการใช้งาน
Paramswitchchar (Sign): กำหนดสตริงหรือถ่านเพื่อระบุสวิตช์หรือพารามิเตอร์ หากไม่ได้กำหนดจะใช้เส้นประสองครั้ง (-) โดยค่าเริ่มต้น
ParamValuesPerator (Sign): กำหนดสตริงหรือถ่านเพื่อแยกชื่อพารามิเตอร์จากค่า (filename = config.json) หากไม่ได้กำหนดเครื่องหมายเท่ากัน (=) จะถูกใช้โดยค่าเริ่มต้น
ParamValueIsNextParam: กำหนดพารามิเตอร์ที่มีค่าที่ไม่มีตัวคั่นค่า (ชื่อไฟล์ C: config.ini)
Paramrequired: กำหนดพารามิเตอร์ตามที่ต้องการ หากไม่พบพารามิเตอร์จะมีการยกข้อยกเว้น
QuickParameter ตรวจสอบประเภทค่าโดยอัตโนมัติ หากคุณกำหนดค่าพารามิเตอร์เป็นจำนวนเต็มและผ่าน alfanumeric จะมีการยกข้อยกเว้น
ช่วยปรับแต่ง: คุณสามารถกำหนดการปรับแต่งสีของคุณเองด้วย ColorizeHelp คุณสมบัติที่เปิดใช้งานจะใช้สีที่กำหนดเองมิฉะนั้นจะใช้ b/w
Parameters.ColorizeHelp.Enabled := True;
Parameters.ColorizeHelp.CommandName := ccCyan;
Parameters.ColorizeHelp.CommandUsage := ccBlue;เมื่อพารามิเตอร์ตรวจพบพารามิเตอร์ความช่วยเหลือจะแสดงเอกสารช่วยเหลือ
Parameters.ShowHelp: แสดงเอกสารช่วยเหลือสร้างโดยอัตโนมัติ:
Parameters v.1.0
Usage: Parameters <command-action> <--HostName=<host>> [--Port <port>] [--Retries=<value>]
[--Config-file=<path>] [--UseTCP] [--Silent] [--Mode=<value>]
[--ShowReport] [--Help]
Simple console application example with Quick.Parameters
Arguments:
Command Command action.
--HostName Define host to connect.
--Port, -p Define Port to connect (default 80)
--Retries Number of max retries.
--Config-file Path to config.
--UseTCP Use TCP connection if present.
--Silent Silent mode.
--Mode Modes (mdAdd, mdSelect, mdRemove)
--Help, -h Show this documentation
การตรวจสอบที่ใช้กันทั่วไป
การตรวจสอบความถูกต้องก่อนและ postcondition ในรูปแบบที่คล่องแคล่ว เงื่อนไข. requires ประเมินตัวแปรสำหรับเงื่อนไขก่อนทำการดำเนินการบางอย่าง เงื่อนไขการตรวจสอบจะประเมินผลลัพธ์ตัวแปรสำหรับเงื่อนไขหลังจากทำการดำเนินการบางอย่าง
Condition.Requires(num, " num " )
.IsInRange( 1 , 10 , ' value for num is out of range ' ); // throws custom error if not in range
.IsNotGreater( 50 ); // throws ArgumentException if not equal to 128
Condition.Requires(myobj, " myobj " )
.WithExceptionOnFailure(EMyException) // throws specific exception on failure
.IsNotNull() // throws ArgumentNullException if null
.Evaluate(myobj.id > 10 ); // myobj.id must be greater than 10
Condition.Requires(text, " text " )
.IsNotEmpty() // throws ArgumentNullException if empty
.StartsWith( " <html> " ) // throws ArgumentException if not starts with <html>
.EndsWith( " </html> " ) // throws ArgumentException if not ends with </html>
.IsNotLowerCase // thows ArgumentException if not lowercase
.Evaluate(text.Contains( " sometxt " ) or test.Contains( ' othertxt ' )); // throws ArgumentException if not evaluatesคุณต้องการเรียนรู้ Delphi หรือพัฒนาทักษะของคุณหรือไม่? LearnDelphi.org