
Quicklib est une bibliothèque Delphi / FiremonKey (Windows, Linux, Android, OSX & iOS) et FPC (Windows & Linux) contenant des fonctions intéressantes et rapides, créées pour simplifier le développement d'applications et la prise en charge de la plate-forme croisée et améliorer la productivité. Delphi Xe8 - Delphi 12 Athènes soutenus.
S'il vous plaît "Star" ce projet dans GitHub! Cela ne coûte que des aides à référencer le code. 
Si vous trouvez ce projet utile, veuillez envisager de faire un don.
Domaines de fonctionnalité:
Description des unités principales:
Mises à jour:
Permettez à une application console de s'exécuter en mode console ou mode de service avec le même code simplifiant les tâches de débogage.
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 ;Simplifie Blob Iteraction avec Azure et 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 ;Fonctions CIDR et 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);Les fonctions sont souvent nécessaires dans le quotidien d'un développeur.
// 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 ;Chronomètre et référence Un morceau de code est simple.
// 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 Écrivez des messages de journal pour consoler avec des couleurs et plus ...
// 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;Enregistrez-vous au disque ou à la mémoire avec des niveaux verbeux et une rotation de l'espace quotidien ou maximum.
// 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);Chargez / enregistrez une configuration en tant que fichiers JSON ou YAML ou clés de registre Windows. Créez une classe de descendance à partir de TappConfigjson, TappConfigyAml ou TappConfigregistry et des propriétés publiées seront chargées / enregistrées. Les configurations de fichiers peuvent être rechargées lors des modifications de fichiers de détection.
// 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 ' );
Surveillance un fichier pour les modifications et lance des événements.
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;Utilise pour travailler avec des objets 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);Envoyer un e-mail avec deux lignes de code.
// 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;Fiffez les classes sûres.
TthreredQueuecs: Version de TthreredQueue avec section critique.
TTHREADObjectList: Liste d'objets de thread Safe.
TthreredQueuelist: Liste de file d'attente de filetage. Autogrow et avec section critique.
TanonymousThread: crée un thread anonyme définissant des méthodes d'exécution et de surtermination Unchained. Utilisez des méthodes EXECUTE_SYNC et Onterminate_Sync Si le code doit mettre à jour l'interface utilisateur.
// 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: lancez un thread de tâche unique automatique avec des politiques de contrôle des défauts et de la réessayer. Les paramètres peuvent être passés et créés dans le code.
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: lancez des tâches en arrière-plan permettant au nombre de travailleurs simultanés avec des politiques de contrôle des défauts et de la réessayer. Utilisez les méthodes addtask_sync et onterminate_sync si le code doit mettre à jour l'interface utilisateur.
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 à la minuterie. Vous pouvez affecter des tâches avec l'heure de début, la répétition des options et la date d'expiration et l'échec des politiques de contrôle. Utilisez addtask_sync, onterminate_sync et onexpired_sync si le code doit mettre à jour l'interface utilisateur. Vous pouvez affecter des méthodes anonymes pour exécuter, exception, résilier et expiration.
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;Gère l'échec et la réessayer des politiques, définissant les tentatives maximales, le temps d'attente entre les textes et le mécanisme de rupture de circuit.
Gère les processus 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 ' );Gère les services 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 de chaîne.
// Format bytes to MB, GB, TB...
FormatBytes( 50000 ) // shows 50KB
FormatBytes( 90000000 ) // shows 90MB Sérialise un objet de / vers le texte JSON. Vous pouvez définir si le public ou la publication sera traité (seul Delphi, FPC RTTI ne prend en charge que les propriétés publiées)
json := ' {"name":"Peter","age":30} ' ;
serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
try
serializer.JsonToObject(user,json);
finally
serializer.Free;
end ;Map champs d'une classe à une autre classe. Permet aux mappages personnalisés de correspondre à différents champs et procédure de cartographie personnalisée pour lancer / convertir manuellement les champs.
// 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);Utilisé comme classe DTO, avec des fonctions JSON sérialisées et de mappage incluses.
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 ;Listes améliorées avec des fonctionnalités d'indexation ou de recherche.
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 stocke n'importe quel type de données et permettez de passer à une autre classe avec des opérateurs intégrés et des autofrees.
var
value : TFlexValue;
str : string;
num : Integer;
begin
value := ' hello ' ;
str := value ;
value := 123 ;
num := value ;
end ;Réseaux améliorés.
TxArray: Array avec des méthodes comme 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: tableau avec des méthodes comme TList que le stockage différents types de valeur dans le même tableau.
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: tableau avec des méthodes comme TList qui peuvent stocker différents types de valeur dans le même tableau et rechercher par nom d'article.
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 ;Structure d'objet YAML.
Tyamlobject: Un objet YAML est et le tableau de paires 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: tableau d'objets ou de scalaires.
yamlarray.AddElement(TYamlPair.Create( ' Age ' , 30 ));
yamlobj.AddPair( ' myarray ' ,yamlarray);Tyamlpair: paire de valeurs de nom. La valeur peut être un objet, un tableau ou un scalaire.
n := yamlobj.GetPair( ' Name ' ). Value as TYamlInteger;Sérialiser / désérialiser l'objet de / vers YAML.
// Serialize
text := YamlSerializer.ObjectToYaml(obj);
// Deserialize
YamlSerializer.YamlToObject(obj,yamltext);Évaluez les propriétés des objets ou les valeurs uniques à l'aide d'expressions.
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 ;Fait des requêtes LINQ sur n'importe quel TobjectList, Tlist, Tarray et TxArray, effectuant SELECT par complex où, comme la syntaxe SQL, la mise à jour et la commande sur votre liste. Où les clauses utilisent des espaces de noms pour déterminer les propriétés imbriquées. LINQ peut rechercher un élément dans un tableau de propriétés. Comprend maintenant et Tarray Helper à ajouter, supprimer et rechercher avec des expressions régulières dans le tableau.
// 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;TCustomHTTPSServer est un simple HTTPServer interfacé avec ses propres implémentations HttpRequest et HttpResponse pour permettre des modifications faciles de moteur HTTPServer. Vous pouvez activer les pages d'erreur personnalisées pour renvoyer des pages personnalisées et des pages d'erreur dynamique. Le thtTPServer est l'implémentation IndyHTTPServer, mais vous pouvez définir le vôtre.
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 ;Les objets ou les chaînes en cache avec un temps d'expiration, pour éviter de générer ces informations à chaque fois sont nécessaires (requêtes de base de données, difficiles à calculer les informations, etc.). TMemoryCache permet de mettre en cache des objets et des chaînes. La version générique TMemoryCache permet de mettre en cache un type défini uniquement.
// 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);Supprimer Value: supprime un objet du cache.
Fournisseurs de moteurs à cache:
TCacheseRializerjson: utilise JSON pour sérialiser les données de cache.
TCacheCompressorGzip: utilise GZIP pour compresser les données de cache.
TCacheCompressorlzo: utilise LZO pour compresser les données de cache.
// create MemoryCache with 20 seconds purge interval and compression with LZO engine
cache := TMemoryCache.Create( 10 , nil ,TCacheCompressorLZO.Create);L'inversion de Control Manager permet d'autocréatiser un objet instancé ou de les injecter auto-injecte dans des classes de constructeurs, pour éviter la dépendance.
Créez un conteneur pour gérer l'injection de dépendance.
iocContainer := TIocContainer.Create;Types d'enregistrement:
Vous devez enregistrer des types avant de pouvoir les injecter. Un type peut être enregistré comme singleton, transitoire. Singleton : Le cycle de vie sera une seule instance pour toutes les injections, similaires à une variable globale. Transient : le cycle de vie sera un cas pour chaque injection. Enregistrez un type d'interface dans le conteneur comme transitoire:
iocContainer.RegisterType<IMultService,TMultService>.AsTransient;Enregistrez un type d'interface comme singleton, déléguer la construction:
iocContainer.RegisterType<ISumService,TSumService>.AsSingleTon.DelegateTo(
function : TSumService
begin
Result := TSumService.Create;
end
);Enregistrer les instances:
Enregistrez un objet d'instance nommé comme transitoire, déléguant la construction:
iocContainer.RegisterInstance<TDivideService>( ' one ' ).AsTransient.DelegateTo(
function : TDivideService
begin
Result := TDivideService.Create(True);
end
);Options d'enregistrement:
Enregistrez les ioptions (seulement Singleton):
iocContainer.RegisterOptions<TMyOptions>(MyOptions);Types de résolution:
APTRATFACTORY: Crée une classe essayant de résoudre tout le paramètre de la méthode de création avec l'injection de dépendance.
MyClass := iocContainer.AbstractFactory<TMyBaseClass>(TMyClass);Résoudre une dépendance à l'interface:
multservice := iocContainer.Resolve<IMultService>;
result := multservice.Mult( 2 , 4 );Résoudre les instances:
Résoudre une dépendance d'instance nommée:
divideservice := iocContainer.Resolve<TDivideService>( ' other ' );
result := divideservice.Divide( 100 , 2 );Les instances d'interface seront libérées automatiquement, mais les dépendances d'instance ne seront libérées que si elles sont définies comme Singleton, les instances transitoires seront détruites par le code.
Vous définissez des sections comme des classes et enregistre comme paramètres de fichier unique. Fonctionne similaire aux options dotnet. Le fichier d'options peut être au format JSON ou YAML.
Définissez votre classe d'options héritée de Toptions et toutes les propriétés publiées seront chargées / sauvegardes. Créer un conteneur d'options, avec jsonserializer et recharger le changement:
Options := TOptionsContainer.Create( ' .options.conf ' ,TJsonOptionsSerializer.Create,True);Ajoutez une section à vos options de conteneur:
Options.AddSection<TLoggingOptions>( ' Logging ' )Configurer les options:
Vous pouvez définir le nom de la section pour enregistrer dans le fichier et déléguer les paramètres par défaut de configuration et les valeurs de validation:
Options.AddSection<TLoggingOptions>( ' Logging ' ).ConfigureOptions(
procedure(aOptions : TLoggingOptions)
begin
aOptions.Path := ' C: ' ;
end
).ValidateOptions;Valider les options:
Valider les options permet de vérifier si les paramètres d'option sont définis entre les plages définies. Cette validation nécessite des attributs personnalisés précédemment attribués aux propriétés de votre classe 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 ;Options d'utilisation: pour récupérer la section des options:
LoggingOptions := Options.GetSection<TLoggingOptions>;
LoggginOptions.Path := ' C:Path ' ;Utilisez des ioptions: IOPTIONS est une interface injectable de dépendance à Toptions. Vous pouvez vous inscrire auprès de IocContainer.RegisterOptions pour transformer l'injectable des méthodes de constructeur.
UIOptions := Options.GetSectionInterface<TUIOptions>. Value ;
UIOptions.WindowColor := clBlue;Options de chargement / enregistrer:
Chargez les options à partir des paramètres du fichier:
options.Load;Enregistrer les options des paramètres du fichier:
options.Save;Si vous avez défini la création de conteneurs avec un paramètre ReloadonChanged sur true, chaque fois que les paramètres de fichier sont modifiés, la configuration sera rechargée. Si vous devez contrôler quand recharger, vous pouvez écouter l'événement:
Options.OnFileModified := procedure
begin
cout('Detected config file modification!',etWarning);
end;
Définissez le pool de connexions, les threads ou tout objet que vous souhaitez contrôler pour éviter les consommateurs de ressources comme les connexions de base de données, les clients HTTP, etc ...
Créer un pool client HTTP:
pool := TObjectPool<THTTPClient>.Create( 5 , 5000 ,procedure( var aInstance : THTTPClient)
begin
aInstance := THTTPClient.Create;
aInstante.UserAgent := ' MyAgent ' ;
end );Obtenez l'objet de la piscine:
httpcli := pool.Get.Item;
statuscode := httpcli.Get( ' https://www.mydomain.com ' ).StatusCode;Définit la liste interfacée et l'objetList avec la prise en charge LINQ héritée.
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;Recherche d'expression pour le tableau des éléments:
users := ListObj.Where( ' Roles CONTAINS ? ' ,[ ' SuperAdmin ' ]).Select;Recherche de prédicat:
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);Voir la section Quick.Linq pour afficher plus de fonctions autorisées.
Template de chaîne Remplacement à l'aide d'un dictionnaire ou d'une fonction déléguée. Vous pouvez spécifier des caractères de jetons cités.
Remplacez le passage d'un dictionnaire:
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);Remplacer par la fonction du délégué:
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 pour vérifier les performances et obtenir la méthode ENTER et quitter la méthode Checkpoint.DEFINE avec un débogage Une directive de compilateur pour être active uniquement lorsque votre application est compilée en mode débogage. Sur Console Apps utilise Console Out par défaut. Vous pouvez passer un enregistreur pour sortir:
TDebugUtils.SetLogger(ilogger);Tracez une partie de votre code:
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 - 12Calculer le temps pour traiter de la fonction point à la sortie:
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,00sCalculez le temps pour traiter du point en point et de la fonction de sortie:
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,50sObtenez une notification lorsque vous entrez et sortez la fonction, et je le chronométrez:
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 Travailler avec les paramètres de ligne de commande sera facile à l'aide de l'extension de ligne de commande. Définissez une classe héritée de TParameters ou TServiceParameters (si vous travaillez avec QuickAppServices) avec vos arguments possibles en tant que propriétés publiées:
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 ;
Utiliser Param:
params := TMyParameter.Create;Lorsque vous appelez votre exe avec - help, vous obtenez une documentation. Si vous devez vérifier un commutateur ou une valeur, vous pouvez faire comme ceci:
if params.Port = 0 then ...
if params.Silent then ...QuickParameters utilise des attributs personnalisés pour définir des conditions de paramètres spéciaux:
CommandDescription: définit le texte pour décrire votre application dans la documentation d'aide.
ParamCommand (numéro): définit la position statique dans la ligne de commande pour les paramètres uniques.
Paramname (nom, alias): définir un nom différent pour le paramètre. Permet d'utiliser des caractères spéciaux non autorisés pour les propriétés de classe (comme le nom de fichier ou config.file). L'argument d'alias facultatif définit un nom de paramètre alternatif (nom normalement court).
Paramhelp (HelpText, ValuEname): définit un nom de texte et de valeur d'aide de commande dans la section d'utilisation.
ParamSwitchChar (signe): définit la chaîne ou le char pour indiquer le commutateur ou le paramètre. S'il n'est pas défini, un double tiret (-) sera utilisé par défaut.
ParamValuesParator (signe): définit la chaîne ou le char pour séparer le nom du paramètre de la valeur (filename = config.json). S'il n'est pas défini, le signe égal (=) sera utilisé par défaut.
ParamValueisNextParam: définit un paramètre avec une valeur sans séparateur de valeur (nom de fichier C: config.ini)
Paramètre: définit un paramètre au besoin. Si Param n'est pas trouvé, une exception sera soulevée.
QuickParameter vérifie automatiquement les types de valeur. Si vous définissez une valeur de paramètre comme entier et passez un alfanumérique, une exception sera soulevée.
Personnalisation d'aide: vous pouvez définir votre propre personnalisation des couleurs avec colorizehelp. La propriété activée utilisera des couleurs personnalisées, sinon B / W seront utilisés.
Parameters.ColorizeHelp.Enabled := True;
Parameters.ColorizeHelp.CommandName := ccCyan;
Parameters.ColorizeHelp.CommandUsage := ccBlue;Lorsque les paramètres détectent le paramètre d'aide, une documentation d'aide sera montrée.
Paramètres.ShowHelp: Affiche la documentation d'aide, générée automatiquement:
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
Validations couramment utilisées.
Validations pré et postconditionnelles dans le style fluide. Condition.Require évalue une variable pour les conditions avant de faire certaines opérations. La condition d'évaluation évalue un résultat variable pour les conditions après certaines opérations.
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 evaluatesVoulez-vous apprendre Delphi ou améliorer vos compétences? Learndelphi.org