
Quicklib adalah perpustakaan Delphi/Firemonkey (Windows, Linux, Android, OSX & iOS) dan FPC (Windows & Linux) yang berisi fungsi yang menarik dan cepat untuk mengimplementasikan, dibuat untuk menyederhanakan pengembangan aplikasi dan dukungan crossplatform dan meningkatkan produktivitas. Delphi XE8 - Delphi 12 Athena didukung.
Tolong "Bintang" proyek ini di GitHub! Tidak ada biaya apa pun selain membantu merujuk kode. 
Jika Anda menemukan proyek ini bermanfaat, pertimbangkan untuk memberikan sumbangan.
Area fungsionalitas:
Unit Utama Deskripsi:
Pembaruan:
Izinkan aplikasi konsol untuk berjalan sebagai mode konsol atau mode layanan dengan kode yang sama menyederhanakan tugas debug.
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 ;Menyederhanakan iteraksi gumpalan dengan Azure dan 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 ;Fungsi CIDR dan IP Range.
// 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);Fungsi sering dibutuhkan dalam sehari -hari pengembang.
// 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 dan Benchmark Sepotong kode sederhana.
// 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 Tulis pesan log untuk menghibur dengan warna dan banyak lagi ...
// 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;Log ke disk atau memori dengan level verbose dan rotasi ruang harian atau maks.
// 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);Muat/simpan konfigurasi sebagai kunci file JSON atau YAML atau Windows Registry. Buat kelas Descend dari TappConfigjson, TappConfigyAml atau TappConfigregistry dan menambahkan properti yang diterbitkan akan dimuat/disimpan. Konfigurasi file dapat dimuat ulang pada perubahan file deteksi.
// 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 ' );
Memantau file untuk perubahan dan melempar peristiwa.
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;Memanfaatkan untuk bekerja dengan objek 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);Kirim email dengan dua baris kode.
// 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;Kelas Aman Thread.
Tthreadedqueuecs: Versi TThreadedQueue dengan bagian kritis.
TThreadObjectList: Daftar Objek Aman Thread.
Tthreadedqueuelist: Daftar Antrian Aman Thread. Autogrow dan dengan bagian kritis.
Tanonymousthread: Membuat utas anonim yang mendefinisikan metode eksekusi dan on -on yang tidak diulang. Gunakan Metode Execute_Sync dan OnterterTinate_Sync jika kode perlu memperbarui 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: Luncurkan utas tugas tunggal otomatis dengan kebijakan kontrol kesalahan & coba lagi. Params dapat diteruskan dan dibuat menjadi kode.
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: Luncurkan tugas di latar belakang yang memungkinkan jumlah pekerja bersamaan dengan kebijakan kontrol kesalahan dan coba lagi. Gunakan metode AddTask_Sync dan OnterterTinate_Sync jika kode perlu memperbarui 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: Alternatif untuk timer. Anda dapat menetapkan tugas dengan waktu mulai, mengulangi opsi dan tanggal kedaluwarsa dan gagal dan mencoba lagi kebijakan kontrol. Gunakan AddTask_Sync, OnterTerminate_sync dan Onexpired_sync jika kode perlu memperbarui UI. Anda dapat menetapkan metode anonim untuk mengeksekusi, pengecualian, mengakhiri dan berakhirnya acara.
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;Mengelola kebijakan gagal dan coba lagi, mendefinisikan retries max, tunggu waktu beet antara retries dan sirkuit mekanisme.
Mengelola proses 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 ' );Mengelola layanan 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 string.
// Format bytes to MB, GB, TB...
FormatBytes( 50000 ) // shows 50KB
FormatBytes( 90000000 ) // shows 90MB Serialisasi objek dari/ke teks JSON. Anda dapat mendefinisikan apakah publik atau yang dipublikasikan akan diproses (hanya Delphi, FPC RTTI hanya mendukung properti yang diterbitkan)
json := ' {"name":"Peter","age":30} ' ;
serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
try
serializer.JsonToObject(user,json);
finally
serializer.Free;
end ;Peta bidang dari satu kelas ke kelas lain. Memungkinkan pemetaan khusus untuk mencocokkan bidang yang berbeda dan prosedur pemetaan khusus untuk melemparkan/mengonversi bidang secara manual.
// 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);Digunakan sebagai kelas DTO, dengan fungsi serial dan pemetaan 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 ;Daftar yang ditingkatkan dengan fitur pengindeksan atau pencarian.
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 menyimpan jenis data apa pun dan memungkinkan lulus ke kelas lain dengan operator dan autofrees terintegrasi.
var
value : TFlexValue;
str : string;
num : Integer;
begin
value := ' hello ' ;
str := value ;
value := 123 ;
num := value ;
end ;Peningkatan array.
TXArray: Array dengan metode seperti 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: Array dengan metode seperti tlist daripada dapat menyimpan jenis nilai yang berbeda ke array yang sama.
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: Array dengan metode seperti tlist daripada yang dapat menyimpan jenis nilai yang berbeda ke dalam array yang sama, dan cari dengan nama item.
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 ;Struktur objek YAML.
TyamlObject: Objek YAML adalah dan array pasangan 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: Array objek atau skalar.
yamlarray.AddElement(TYamlPair.Create( ' Age ' , 30 ));
yamlobj.AddPair( ' myarray ' ,yamlarray);Tyamlpair: Name-Value Pair. Nilai dapat berupa objek, array atau skalar.
n := yamlobj.GetPair( ' Name ' ). Value as TYamlInteger;Serialize/deserialize objek dari/ke yaml.
// Serialize
text := YamlSerializer.ObjectToYaml(obj);
// Deserialize
YamlSerializer.YamlToObject(obj,yamltext);Mengevaluasi sifat objek atau nilai tunggal menggunakan ekspresi.
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 ;Membuat kueri LINQ untuk setiap tobjectlist, tlist, tarray dan txArray, melakukan select by complex di mana seperti sintaks SQL, perbarui dan pesan di daftar Anda. Di mana klausa menggunakan namespaces untuk menentukan sifat bersarang. Linq dapat mencari elemen ke dalam array properti. Sekarang termasuk dan Tarray Helper untuk menambah, menghapus dan mencari dengan ekspresi reguler ke dalam array.
// 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 adalah httpserver antarmuka sederhana dengan implementasi httpRequest dan httpresponse sendiri untuk memungkinkan perubahan mesin httpserver yang mudah. Anda dapat mengaktifkan halaman kesalahan khusus untuk mengembalikan halaman yang disesuaikan dan halaman kesalahan dinamis. Thttpserver adalah implementasi IndyHttpserver, tetapi Anda dapat mendefinisikan sendiri.
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 ;Mengacak objek atau string dengan waktu kedaluwarsa, untuk menghindari menghasilkan info ini setiap kali diperlukan (kueri database, sulit untuk menghitung info, dll). TMemoryCache memungkinkan untuk cache benda dan string. Versi generik TMemoryCache memungkinkan untuk menyimpan tipe yang ditentukan saja.
// 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: Menghapus objek dari cache.
Penyedia mesin cache:
Tcacheserializejson: Menggunakan JSON untuk membuat serial data cache.
Tcachecompressorgzip: Menggunakan GZIP untuk mengompres data cache.
Tcachecompressorlzo: menggunakan LZO untuk mengompres data cache.
// create MemoryCache with 20 seconds purge interval and compression with LZO engine
cache := TMemoryCache.Create( 10 , nil ,TCacheCompressorLZO.Create);Inversion of Control Manager memungkinkan autocreate antarmaced O objek yang dipasang atau secara otomatis mengarahkan mereka di kelas konstruktor, untuk menghindari ketergantungan.
Buat wadah untuk mengelola injeksi ketergantungan.
iocContainer := TIocContainer.Create;Jenis Daftar:
Anda perlu mendaftar jenis sebelum dapat menyuntikkannya. Jenis dapat didaftarkan sebagai singleton, sementara. Singleton : Siklus hidup akan menjadi satu contoh tunggal untuk semua suntikan, mirip dengan variabel global. Transient : Siklus hidup akan menjadi satu contoh per setiap suntikan. Daftarkan jenis antarmuka ke dalam wadah sebagai transien:
iocContainer.RegisterType<IMultService,TMultService>.AsTransient;Daftarkan jenis antarmuka sebagai singleton, mendelegasikan konstruksi:
iocContainer.RegisterType<ISumService,TSumService>.AsSingleTon.DelegateTo(
function : TSumService
begin
Result := TSumService.Create;
end
);Daftar instance:
Daftarkan objek instance bernama sebagai konstruksi sementara, mendelegasikan:
iocContainer.RegisterInstance<TDivideService>( ' one ' ).AsTransient.DelegateTo(
function : TDivideService
begin
Result := TDivideService.Create(True);
end
);Opsi Daftar:
Daftar ioptions (hanya singleton):
iocContainer.RegisterOptions<TMyOptions>(MyOptions);Jenis Tekad:
AbtractFactory: Membuat kelas yang mencoba menyelesaikan semua parameter metode penciptaan dengan injeksi ketergantungan.
MyClass := iocContainer.AbstractFactory<TMyBaseClass>(TMyClass);Menyelesaikan ketergantungan antarmuka:
multservice := iocContainer.Resolve<IMultService>;
result := multservice.Mult( 2 , 4 );Ikuti instance:
Menyelesaikan ketergantungan instance bernama:
divideservice := iocContainer.Resolve<TDivideService>( ' other ' );
result := divideservice.Divide( 100 , 2 );Instance antarmuka akan dibebaskan secara otomatis, tetapi dependensi instance hanya akan dibebaskan jika didefinisikan sebagai singleton, instance sementara akan dihancurkan oleh kode.
Anda mendefinisikan bagian sebagai kelas dan menyimpan sebagai pengaturan file tunggal. Bekerja mirip dengan opsi dotnet. File opsi dapat dalam format JSON atau YAML.
Tentukan kelas opsi Anda yang diwarisi dari toptions dan semua properti yang diterbitkan akan dimuat/menyimpan. Buat wadah opsi, dengan jsonserializer dan muat ulang pada perubahan:
Options := TOptionsContainer.Create( ' .options.conf ' ,TJsonOptionsSerializer.Create,True);Tambahkan bagian ke opsi wadah Anda:
Options.AddSection<TLoggingOptions>( ' Logging ' )Konfigurasikan Opsi:
Anda dapat mendefinisikan nama bagian untuk disimpan ke dalam file dan mendelegasikan pengaturan default konfigurasi dan memvalidasi nilai:
Options.AddSection<TLoggingOptions>( ' Logging ' ).ConfigureOptions(
procedure(aOptions : TLoggingOptions)
begin
aOptions.Path := ' C: ' ;
end
).ValidateOptions;Validasi Opsi:
Validasi Opsi Memungkinkan Verifikasi Jika Pengaturan Opsi diselesaikan antara rentang yang ditentukan. Validasi ini membutuhkan atribut khusus yang ditetapkan sebelumnya untuk properti di kelas toptions Anda.
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 ;Gunakan Opsi: Untuk Mengambil Bagian Opsi:
LoggingOptions := Options.GetSection<TLoggingOptions>;
LoggginOptions.Path := ' C:Path ' ;Gunakan iOptions: ioptions adalah antarmuka suntik ketergantungan ke toptions. Anda dapat mendaftar dengan ioccontainer.registeroptions untuk membuat injeksi ke dalam metode konstruktor.
UIOptions := Options.GetSectionInterface<TUIOptions>. Value ;
UIOptions.WindowColor := clBlue;Opsi Muat/Simpan:
Muat Opsi dari Pengaturan File:
options.Load;Simpan opsi untuk pengaturan file:
options.Save;Jika Anda menentukan pembuatan kontainer dengan parameter reloadonchanged ke True, setiap kali pengaturan file diubah, konfigurasi akan dimuat ulang. Jika Anda perlu mengontrol kapan harus memuat ulang, Anda dapat mendengarkan acara tersebut:
Options.OnFileModified := procedure
begin
cout('Detected config file modification!',etWarning);
end;
Tentukan kumpulan koneksi, utas atau objek apa pun yang ingin Anda kendalikan untuk menghindari konsumsi sumber daya seperti koneksi database, klien HTTP, dll ...
Buat kumpulan klien http:
pool := TObjectPool<THTTPClient>.Create( 5 , 5000 ,procedure( var aInstance : THTTPClient)
begin
aInstance := THTTPClient.Create;
aInstante.UserAgent := ' MyAgent ' ;
end );Dapatkan objek dari biliar:
httpcli := pool.Get.Item;
statuscode := httpcli.Get( ' https://www.mydomain.com ' ).StatusCode;Mendefinisikan daftar antarmuka dan daftar objek dengan dukungan LINQ diwariskan.
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;Pencarian ekspresi untuk array item:
users := ListObj.Where( ' Roles CONTAINS ? ' ,[ ' SuperAdmin ' ]).Select;Pencarian Predikat:
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);Lihat bagian Quick.linq untuk melihat lebih banyak fungsi yang diizinkan.
Template string mengganti menggunakan fungsi kamus atau delegasi. Anda dapat menentukan karakter token yang dikutip.
Ganti melewati kamus:
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);Ganti dengan fungsi delegasi:
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 utils untuk memeriksa kinerja dan mendapatkan enter dan keluar metode pemeriksaan. Pada aplikasi konsol menggunakan konsol keluar secara default. Anda dapat melewati logger untuk output di:
TDebugUtils.SetLogger(ilogger);Lacak bagian dari kode Anda:
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 - 12Hitung waktu untuk memproses dari fungsi titik keluar:
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,00sHitung waktu untuk memproses dari titik ke titik dan keluar fungsi:
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,50sDapatkan pemberitahuan saat masuk dan keluar fungsi, dan kali itu:
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 Bekerja dengan parameter CommandLine akan mudah menggunakan ekstensi CommandLine. Tentukan kelas yang diwarisi dari TParameter atau TserviceParameter (jika bekerja dengan QuickAppServices) dengan kemungkinan argumen Anda sebagai properti yang diterbitkan:
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 ;
Gunakan param:
params := TMyParameter.Create;Saat Anda menghubungi EXE Anda dengan -membantu Anda mendapatkan dokumentasi. Jika Anda perlu memeriksa sakelar atau nilai, Anda dapat melakukannya seperti ini:
if params.Port = 0 then ...
if params.Silent then ...QuickParameters menggunakan atribut khusus untuk menentukan kondisi parameter khusus:
CommandDescription: Menentukan teks untuk menjelaskan aplikasi Anda dalam dokumentasi bantuan.
ParamCommand (Nomor): Menentukan posisi statis ke dalam Commandline untuk parameter tunggal.
Paramname (nama, alias): Tentukan nama yang berbeda untuk parameter. Memungkinkan untuk menggunakan karakter khusus yang tidak diizinkan untuk properti kelas (seperti file-name atau config.file). Argumen alias opsional mendefinisikan nama parameter alternatif (biasanya nama pendek).
Paramhelp (Helptext, ValueName): Menentukan teks bantuan CommandLine dan nama nilai di bagian Penggunaan.
ParamswitchChar (tanda): Menentukan string atau char untuk menunjukkan sakelar atau parameter. Jika tidak ditentukan, dasbor ganda (-) akan digunakan secara default.
ParamValuesEparator (Sign): Menentukan string atau char ke nama parameter terpisah dari nilai (fileName = config.json). Jika tidak ditentukan, tanda yang sama (=) akan digunakan secara default.
ParamValueIsNextParam: Menentukan parameter dengan nilai tanpa pemisah nilai (nama file c: config.ini)
Paramrequired: Menentukan parameter sesuai kebutuhan. Jika Param tidak ditemukan, pengecualian akan dinaikkan.
QuickParameter secara otomatis memeriksa jenis nilai. Jika Anda mendefinisikan nilai parameter sebagai integer, dan lulus alfanumerik, pengecualian akan dinaikkan.
Bantuan Kustomisasi: Anda dapat menentukan kustomisasi warna Anda sendiri dengan ColorizeHelp. Properti yang diaktifkan akan menggunakan warna khusus, jika tidak, B/W akan digunakan.
Parameters.ColorizeHelp.Enabled := True;
Parameters.ColorizeHelp.CommandName := ccCyan;
Parameters.ColorizeHelp.CommandUsage := ccBlue;Ketika parameter mendeteksi parameter bantuan, dokumentasi bantuan akan ditampilkan.
Parameter.showhelp: menunjukkan dokumentasi bantuan, dihasilkan secara otomatis:
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
Validasi yang umum digunakan.
Validasi pra dan postkondisi dalam gaya fasih. Kondisi. Perlu mengevaluasi variabel untuk kondisi sebelum melakukan beberapa operasi. Kondisi. Pastikan mengevaluasi hasil variabel untuk kondisi setelah melakukan beberapa operasi.
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 evaluatesApakah Anda ingin belajar Delphi atau meningkatkan keterampilan Anda? learndelphi.org