
Quicklib ist eine Bibliothek von Delphi/Fironemekey (Windows, Linux, Android, OSX & IOS) und FPC (Windows & Linux), die interessante und schnell implementierte Funktionen enthält, die zur Vereinfachung der Anwendungsentwicklung und der Cross -Platform -Unterstützung und der Verbesserung der Produktivität erstellt wurden. Delphi XE8 - Delphi 12 Athen unterstützt.
Bitte "Star" dieses Projekt in GitHub! Es kostet nichts anderes, als auf den Code zu verweisen. 
Wenn Sie dieses Projekt nützlich finden, erwägen Sie bitte eine Spende.
Bereiche der Funktionalität:
Haupteinheiten Beschreibung:
Aktualisierungen:
Lassen Sie eine Konsolen -App als Konsolenmodus oder Service -Modus mit denselben Code -vereinfachten Debug -Aufgaben ausgeführt.
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 ;Vereinfacht die Blob -Iteraktion mit Azure und Amazon Cloud -Speicher.
// 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- und IP -Bereichsfunktionen.
// 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);Funktionen, die im Alltag eines Entwicklers häufig benötigt werden.
// 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 und Benchmark Ein Stück Code ist einfach.
// 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 Schreiben Sie Protokollnachrichten in Konsolen mit Farben und mehr ...
// 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;Protokollieren Sie auf Disk oder Speicher mit ausführlichen Ebenen und täglicher oder maximaler Raumrotation.
// 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);Laden/speichern Sie eine Konfiguration als JSON- oder YAML -Datei oder Windows -Registrierungsschlüssel. Erstellen Sie eine Descend -Klasse von Tappconfigjson, Tappconfigyaml oder TappConfigregistry und werden veröffentlichte Eigenschaften geladen/gespeichert. Dateienkonfigurationen können bei Änderungen der Dateien erfassen.
// 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 ' );
Überwachen Sie eine Datei für Änderungen und wirft Ereignisse aus.
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;Utils für die Arbeit mit JSON -Objekten.
// 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);Senden Sie E -Mail mit zwei Codezeilen.
// 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;Thread Safe -Klassen.
Threedequeuecs: Version von ThreeDQueue mit kritischem Abschnitt.
TThreadObjectList: Thread Safe -Objektliste.
TThreedequeuelist: Thread Safe Warteschlangenliste. Autodrow und mit kritischem Abschnitt.
TanonymousThread: Erstellt anonymer Thread, die Unchained Execute definieren und zu terminieren. Verwenden Sie Execute_Sync und Onterterate_Sync -Methoden, wenn der Code die Benutzeroberfläche aktualisieren muss.
// 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: Starten Sie einen Autofree -Task -Thread mit Fehler- und Wiederholungssteuerungsrichtlinien. Parameter können übergeben und in Code erstellt werden.
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: Startaufgaben im Hintergrund, die eine Anzahl der gleichzeitigen Arbeitnehmer mit Fehler- und Wiederholungssteuerungsrichtlinien ermöglichen. Verwenden Sie addtask_sync und onterterate_sync -Methoden, wenn der Code die Benutzeroberfläche aktualisieren muss.
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: Alternative zum Timer. Sie können Aufgaben mit Startzeit, Wiederholungsoptionen und Ablaufdatum zuweisen und die Steuerungspolitik wiederholen. Verwenden Sie addtask_sync, onterterate_ync und onexpired_sync, wenn der Code die Benutzeroberfläche aktualisieren muss. Sie können anonyme Methoden zur Ausführung, Ausnahme, Beendigung und Ablauf von Ereignissen zuweisen.
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;Verwaltet Fail- und Wiederholung von Richtlinien, definiert maximale Wiederholungen, Wartezeitbezäune zwischen Wiederholungen und Schaltkreis -Bruch -Mekanismus.
Verwaltet Windows -Prozesse.
// 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 ' );Verwaltet Windows Services.
// 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 ' );String -Format.
// Format bytes to MB, GB, TB...
FormatBytes( 50000 ) // shows 50KB
FormatBytes( 90000000 ) // shows 90MB Serialisiert ein Objekt von/nach JSON -Text. Sie können definieren, ob öffentlich oder veröffentlicht wird (nur Delphi, FPC RTTI unterstützt nur veröffentlichte Eigenschaften).
json := ' {"name":"Peter","age":30} ' ;
serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
try
serializer.JsonToObject(user,json);
finally
serializer.Free;
end ;Kartenfelder von einer Klasse zu einer anderen Klasse. Ermöglicht benutzerdefinierte Zuordnungen, die verschiedenen Felder und benutzerdefinierten Mapping -Prozeduren übereinstimmen, um Felder manuell zu gießen/zu konvertieren.
// 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);Wird als DTO -Klasse verwendet, wobei JSON -Serialisierungs- und Mapping -Funktionen enthalten sind.
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 ;Verbesserte Listen mit Indizier- oder Suchfunktionen.
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 speichert einen beliebigen Datentyp und ermöglicht die Übergabe an eine andere Klasse mit integrierten Operatoren und Autofreen.
var
value : TFlexValue;
str : string;
num : Integer;
begin
value := ' hello ' ;
str := value ;
value := 123 ;
num := value ;
end ;Verbesserte Arrays.
TxArray: Array mit Methoden wie 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 mit Methoden wie Tlist als kann verschiedene Werttypen in das gleiche Array speichern.
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 mit Methoden wie Tlist, als verschiedene Werttypen in demselben Array speichern und nach Elementnamen suchen können.
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 -Objektstruktur.
Tyamlobject: Ein YAML -Objekt ist und Array von YamlValue -Paaren.
// 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 von Objekten oder Skalaren.
yamlarray.AddElement(TYamlPair.Create( ' Age ' , 30 ));
yamlobj.AddPair( ' myarray ' ,yamlarray);Tyamlpair: Namenswertepaar. Wert kann Objekt, Array oder Skalar sein.
n := yamlobj.GetPair( ' Name ' ). Value as TYamlInteger;Serialisieren/Deserialisieren von Objekt von/bis yaml.
// Serialize
text := YamlSerializer.ObjectToYaml(obj);
// Deserialize
YamlSerializer.YamlToObject(obj,yamltext);Bewerten Sie Objekteigenschaften oder einzelne Werte mit Ausdrücken.
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 ;Führen Sie LINQ -Abfragen zu einer beliebigen TobjectList, Tlist, Tarray und TXArray durch, die ausgewählt werden, wobei die SQL -Syntax, die Aktualisierung und die Bestellung Ihrer Liste ausgewählt werden. Wo Klauseln Namespaces verwendet, um verschachtelte Eigenschaften zu bestimmen. Linq kann nach einem Element in einem Eigenschaftsarray suchen. Enthält jetzt und Tarray -Helfer zum Hinzufügen, Entfernen und Suchen mit regulären Ausdrücken in 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 ist ein einfacher HTTPServer mit eigenen HTTPREquest- und HTTPresponse -Implementierungen, um einfache Änderungen der HTTPServer -Engine zu ermöglichen. Sie können benutzerdefinierte Fehlerseiten aktivieren, um angepasste Seiten und dynamische Fehlerseiten zurückzugeben. THTTPSERVER ist die IndyhttpServer -Implementierung, aber Sie können Ihre eigenen definieren.
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 ;Caches Objekte oder Zeichenfolgen mit einer Ablaufzeit, um zu vermeiden, dass jedes Mal diese Informationen benötigt werden (Datenbankabfragen, schwer zu berechnung zu berechnen usw.). TMemoryCache ermöglicht es, Objekte und Zeichenfolgen zu speichern. Generische Version TMEMORYCache ermöglicht es, nur einen definierten Typ zu speichern.
// 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);REMEDVALUE: Entfernt ein Objekt aus dem Cache.
Cache -Motoranbieter:
Tcacheserializerjson: verwendet JSON, um Cache -Daten zu serialisieren.
TcacheCompressorgZIP: Verwendet GZIP, um Cache -Daten zu komprimieren.
TCACHECOMPRESSORLZO: Verwendet LZO, um Cache -Daten zu komprimieren.
// create MemoryCache with 20 seconds purge interval and compression with LZO engine
cache := TMemoryCache.Create( 10 , nil ,TCacheCompressorLZO.Create);Die Inversion des Kontrollmanagers ermöglicht die autokratische OF -IN -Instanzobjekt oder autoinjektion in Konstruktorklassen, um Abhängigkeit zu vermeiden.
Erstellen Sie einen Container, um die Abhängigkeitsinjektion zu verwalten.
iocContainer := TIocContainer.Create;Registrieren Sie Typen:
Sie müssen Typen registrieren, bevor Sie sie injizieren können. Ein Typ kann als Singleton registriert werden, vorübergehend. Singleton : Der Lebenszyklus wird für alle Injektionen eine einzige Instanz sein, ähnlich einer globalen Variablen. Transient : Der Lebenszyklus ist eine Instanz pro Injektion. Registrieren Sie einen Schnittstellentyp als vorübergehend in den Container:
iocContainer.RegisterType<IMultService,TMultService>.AsTransient;Registrieren Sie einen Schnittstellentyp als Singleton und delegieren Sie die Konstruktion:
iocContainer.RegisterType<ISumService,TSumService>.AsSingleTon.DelegateTo(
function : TSumService
begin
Result := TSumService.Create;
end
);Instanzen registrieren:
Registrieren Sie ein benanntes Instanzobjekt als vorübergehende, delegierende Konstruktion:
iocContainer.RegisterInstance<TDivideService>( ' one ' ).AsTransient.DelegateTo(
function : TDivideService
begin
Result := TDivideService.Create(True);
end
);Optionen registrieren:
Registrieren Sie IOTTIONS (nur Singleton):
iocContainer.RegisterOptions<TMyOptions>(MyOptions);Auflösungsarten:
AbtractFactory: Erstellt eine Klasse, die versucht, den gesamten Parameter der Erstellungsmethode mit Abhängigkeitsinjektion zu beheben.
MyClass := iocContainer.AbstractFactory<TMyBaseClass>(TMyClass);Lösen Sie eine Schnittstellenabhängigkeit:
multservice := iocContainer.Resolve<IMultService>;
result := multservice.Mult( 2 , 4 );Instanzen lösen:
Lösen Sie eine benannte Instanzabhängigkeit:
divideservice := iocContainer.Resolve<TDivideService>( ' other ' );
result := divideservice.Divide( 100 , 2 );Schnittstelleninstanzen werden automatisch befreit, aber Instanzabhängigkeiten werden nur dann befreit, wenn sie als Singleton definiert sind. Transiente Instanzen werden durch Code zerstört.
Sie definieren Abschnitte als Klassen und speichern als Einzeldateieinstellungen. Funktioniert ähnlich wie bei Dotnet -Optionen. Die Optionsdatei kann im JSON- oder YAML -Format vorliegen.
Definieren Sie Ihre Optionskurs, die aus Tops geerbt wurde, und alle veröffentlichten Eigenschaften werden geladen/speichern. Erstellen Sie Optionen Container, mit JsonSerializer und neu laden beim Wandel neu:
Options := TOptionsContainer.Create( ' .options.conf ' ,TJsonOptionsSerializer.Create,True);Fügen Sie Ihren Containeroptionen einen Abschnitt hinzu:
Options.AddSection<TLoggingOptions>( ' Logging ' )Optionen konfigurieren:
Sie können den Abschnittsnamen definieren, um die Standardeinstellungen für Datei- und Delegieren der Konfiguration zu speichern und Werte zu validieren:
Options.AddSection<TLoggingOptions>( ' Logging ' ).ConfigureOptions(
procedure(aOptions : TLoggingOptions)
begin
aOptions.Path := ' C: ' ;
end
).ValidateOptions;Optionen validieren:
Überprüfen Sie die Optionen, ob die Optionseinstellungen zwischen definierten Bereichen festgelegt sind. Diese Validierung erfordert zuvor zugewiesene benutzerdefinierte Attribute an Eigenschaften in Ihrer Topion -Klasse.
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 ;Optionen verwenden: Option Abrufenabschnitt: Abschnitt Option:
LoggingOptions := Options.GetSection<TLoggingOptions>;
LoggginOptions.Path := ' C:Path ' ;Verwenden Sie IOTTICTIONS: IOTTICTIONS ist eine injizierbare Abhängigkeitsschnittstelle von Tops. Sie können sich bei ioccontainer.registerOptions registrieren, um in Konstruktormethoden injizierbar zu machen.
UIOptions := Options.GetSectionInterface<TUIOptions>. Value ;
UIOptions.WindowColor := clBlue;Optionen laden/speichern:
Optionen aus den Dateieinstellungen laden:
options.Load;Optionen speichern, um Einstellungen zu dateien:
options.Save;Wenn Sie die Containererstellung mit dem Reloadonchanged -Parameter zu True definiert haben, wird jedes Mal die Dateieinstellungen geändert, und die Konfiguration wird neu geladen. Wenn Sie steuern müssen, wann Sie neu laden müssen, können Sie das Ereignis anhören:
Options.OnFileModified := procedure
begin
cout('Detected config file modification!',etWarning);
end;
Definieren Sie den Pool der Verbindung, Threads oder eines Objekts, das Sie steuern möchten, um die Verbrauchsdatenbankverbindungen, HTTP -Clients usw. zu vermeiden.
Erstellen Sie den HTTP -Clientpool:
pool := TObjectPool<THTTPClient>.Create( 5 , 5000 ,procedure( var aInstance : THTTPClient)
begin
aInstance := THTTPClient.Create;
aInstante.UserAgent := ' MyAgent ' ;
end );Holen Sie sich Objekt aus dem Pool:
httpcli := pool.Get.Item;
statuscode := httpcli.Get( ' https://www.mydomain.com ' ).StatusCode;Definiert mit der LINQ -Unterstützung geerbt.
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;Ausdrucksuche nach Element -Array:
users := ListObj.Where( ' Roles CONTAINS ? ' ,[ ' SuperAdmin ' ]).Select;Prädikat -Suche:
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);Siehe Abschnitt Quick.LinQ, um weitere zulässige Funktionen anzuzeigen.
String -Vorlage ersetzt mithilfe einer Wörterbuch- oder Delegiertenfunktion. Sie können zitierte Token -Chars angeben.
Ersetzen Sie ein Wörterbuch: ein Wörterbuch:
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);Ersetzen Sie durch die Delegierfunktion:
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);Debugug utils, um die Leistung zu überprüfen und den Checkpoint für die Eingabetmethode einzugeben. Auf Konsolen -Apps verwendet die Konsole standardmäßig. Sie können einen Logger übergeben, um auszugeben:
TDebugUtils.SetLogger(ilogger);Verfolgen Sie einen Teil Ihres Codes:
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 - 12Berechnen Sie die Zeit, um von Punkt zu Beenden zu verarbeiten: Funktionen:
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,00sBerechnen Sie die Zeit, die die Funktion von Punkt zu Punkt und Ausgang verarbeiten: Funktionen:
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,50sErhalten Sie eine Benachrichtigung, wenn Sie die Funktion eingeben und beenden, und zeitweise:
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 Die Arbeit mit Befehlsleitungsparametern ist einfach, wenn Sie die Befehlszeilenerweiterung verwenden. Definieren Sie eine Klasse, die von TParameters oder TServiceParameters (bei der Arbeit mit QuickAppServices) mit Ihren möglichen Argumenten als veröffentlichte Eigenschaften geerbt wurde:
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 ;
Verwenden Sie Param:
params := TMyParameter.Create;Wenn Sie Ihr Exe mit -Help anrufen, erhalten Sie eine Dokumentation. Wenn Sie nach einem Switch oder einem Wert suchen müssen, können Sie dies mögen:
if params.Port = 0 then ...
if params.Silent then ...QuickParameters verwendet benutzerdefinierte Attribute, um spezielle Parameterbedingungen zu definieren:
Befehlsschreibung: Definiert Text, um Ihre Anwendung in der Hilfsdokumentation zu beschreiben.
Paramcommand (Nummer): Definiert die statische Position für einzelne Parameter in die Befehlszeile.
ParamName (Name, Alias): Definieren Sie einen unterschiedlichen Namen für den Parameter. Ermöglicht die Verwendung von Sonderzeichen, die für Klasseneigenschaften nicht zulässig sind (z. B. Dateiname oder config.file). Optionales Alias -Argument definiert einen alternativen Parameternamen (normalerweise kurzer Name).
ParamHelp (Helptext, Valuename): Definiert einen Befehlszeilungshilfe -Text- und Wertnamen im Abschnitt Verwendungsnutzung.
ParamswitchChar (Zeichen): Definiert String oder Zeichen, um Switch oder Parameter anzugeben. Wenn nicht definiert, wird standardmäßig ein doppelter Dash (-) verwendet.
ParamvalueSeParator (Zeichen): Definiert String oder Zeichen, um den Parameternamen von Wert zu separat (Dateiname = config.json). Wenn nicht definiert, wird das gleiche Zeichen (=) standardmäßig verwendet.
ParamvalueisNextParam: Definiert einen Parameter mit einem Wert ohne Wertschöpfung (Dateiname C: config.ini)
Paramrequired: Definiert einen Parameter wie erforderlich. Wenn der Param nicht gefunden wird, wird eine Ausnahme erhöht.
QuickParameter prüft automatisch nach Werttypen. Wenn Sie einen Parameterwert als Ganzzahl definieren und einen Alfanumerikum übergeben, wird eine Ausnahme angehoben.
Hilfeanpassung: Sie können Ihre eigene Farbanpassung mit ColorSehelp definieren. Die aktivierte Eigenschaft verwendet benutzerdefinierte Farben, ansonsten werden B/W verwendet.
Parameters.ColorizeHelp.Enabled := True;
Parameters.ColorizeHelp.CommandName := ccCyan;
Parameters.ColorizeHelp.CommandUsage := ccBlue;Wenn Parameter den Hilfsparameter erkennen, wird die Hilfsdokumentation angezeigt.
Parameter.ShowHelp: zeigt Hilfedokumentation, automatisch generiert:
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
Häufig verwendete Validierungen.
Vor- und Postkonditionsvalidierungen im fließenden Stil. Condition. -Erzählungen bewerten eine Variable für Bedingungen, bevor einige Operationen durchgeführt werden. Condition.Endesures bewertet ein variables Ergebnis für Bedingungen nach einigen Operationen.
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 evaluatesMöchten Sie Delphi lernen oder Ihre Fähigkeiten verbessern? Learndelphi.org