
QuickLib - это библиотека Delphi/Firemonkey (Windows, Linux, Android, OSX & IOS) и FPC (Windows & Linux), содержащая интересные и быстрые для реализации функций, созданных для упрощения разработки приложений и поддержки кроссплатформы и повышения производительности. Delphi XE8 - Delphi 12 Афины поддерживают.
Пожалуйста, «звезда» этот проект в GitHub! Это ничего не стоит, кроме как помогает ссылаться на код. 
Если вы найдете этот проект полезным, пожалуйста, рассмотрите возможность сделать пожертвование.
Области функциональности:
Описание основных подразделений:
Обновления:
Позвольте консольному приложению запускать в качестве режима консоли или режим обслуживания с теми же упрощающими задачами отладки кода.
if not AppService.IsRunningAsService then
begin
...your code running as console
end
else
begin
AppService.ServiceName := ' MyService ' ;
AppService.DisplayName := ' MyServicesvc ' ;
// you can pass an anonymous method to events
AppService.OnStart := procedure
begin
...your start code
end ;
AppService.OnExecute := YourExecuteFunction;
AppService.OnStop := YourStopFunction;
AppService.CheckParams;
end ;Упрощает итерацию Blob с помощью Azure и Amazon Cloud Storage.
// connect to a Azure blobstorage
QuickAzure := TQuickAzure.Create(AzureAccountName,AzureAccountKey);
// download a blob file to a stream
done := QuickAzure.GetBlob( ' MyContainer ' , ' MyFile.jpg ' ,ResponseInfo,MyStream);
// check if exists a folder
found := ExistFolder( ' MyContainer ' , ' /Public/Documents/Personal ' );
// list blobs starting with a pattern (recursively or not)
for azBlob in ListBlobs( ' MyContainer ' , ' /Public/Documents ' ,Recursive,ResponseInfo) do
begin
if azBlob.Size > 1000 then Showmessage(azBlob. Name );
end ;Функции диапазона CIDR и IP.
// convert ip string to integer
IPv4ToInt( ' 192.168.1.10 ' );
// get first and last ip of a subnet scope
GetIpRange( ' 192.168.100.0 ' , ' 255.255.255.0 ' ,LowIp,HighIP);Функции часто необходимы в повседневной жизни разработчика.
// coverts UTC time TDateTime to Local date time
UTCToLocalTime(MyUTCTime);
// generate a 10 char length random password with alfanumeric and signs.
RandomPassword( 10 ,[pfIncludeNumbers,pfIncludeSigns]);
// Capitalize every word of a phrase
CapitalizeAll( ' the grey fox ' ); // returns "The Grey Fox"
// Simple TCounter and TTimeCounter for loops
counter := TCounter;
counter.Init( 200 );
timecounter : TTimeCounter;
timecounter.Init( 10000 );
while true do
begin
Inc(n);
{ your procedural process here }
// every 200 steps writes to console
if counter.Check then writeln(Format( ' Processed %d entries ' ,[n]));
// every 10 seconds writes to console
if timecounter.Check then writeln( ' Im working... ' );
end ;Хронометр и сравнительные знаки кусок кода прост.
// get elapsed time execution of a code part
Chrono := TChronometer.Create(False);
Chrono.Start;
...code you need benchmark
Chrono.Stop;
// shows elapsed time in LongTime format (2 hour(s) and 10 minute(s))
Showmessage(Chrono.TimeElapsed(True));
// shows elapsed time in ShortTime format (02:10:00)
Showmessage(Chrono.TimeElapsed(False));
// get benchmak info of a process
Chrono := TChronoBenchMark.Create;
Chrono.TotalProcess := 100000 ;
for i := 1 to 10000 do
begin
{ your process here }
Chrono.CurrentProcess := i;
// shows estimated time your process will take in x hour(s), x minute(s) x second(s) format
writeln(Chrono.EstimatedTime(True));
// shows speed: num items per second processed of your process
writeln(Format( ' Items processed %d/sec ' ,[Chrono.Speed]));
end ;
writeln(Chrono.ElapsedTime(False)); // shows total time elapsed in 00:00:00 format Напишите сообщения журнала в консоли с цветами и многим другим ...
// define which level of output needed
Console.Verbose := LOG_DEBUG;
// writes line to console in red color
cout( ' Error x ' ,etError);
// writes formatted line in green color
coutFmt( ' Proccess %s finished ' ,[ProccesName],etSuccess);
// writes integer
cout( 12348 );
// Connect a QuickLog and write to disk and screen with one line of code (with independent verbose levels)
MyQuickLog := TQuickLog.Create;
MyQuickLog.Verbose := LOG_ALL;
Console.Verbose := LOG_ONLYERRORS;
Console.Log := MyQuickLog;Войдите на диск или память с уровнями словеса и ежедневным или максимальным вращением пространства.
// write a header on start with info as running path, appname, debugmode, user, etc...
Log.ShowHeader := True;
// sets log with rotation at 20MB
Log.SetLog( ' .mylog.log ' ,False, 20 );
// write an error message
Log.Add( ' Error x ' ,etError);
// write formatted error message
Log.Add( ' Error is %s ' ,[ErrorStr],etError);Загрузите/сохранить конфигурацию как файл JSON или YAML или ключи реестра Windows. Создайте спускной класс из Tappconfigjson, Tappconfigyaml или Tappconfigeristry, и добавлены опубликованные свойства, которые будут загружены/сохранены. Конфигурации файлов могут быть перезагружены при обнаружении изменений файлов.
// create a class heritage
TMyConfig = class (TAppConfigJson)
private
fName : string;
fSurname : string;
fStatus : Integer;
published
property Name : string read fName write fName;
property SurName : string read fSurname write fSurname;
property Status : Integer read fStatus write fStatus;
end ;
// create your config to json file
// Add Quick.Config.Json to your uses
MyConfig := TMyConfig.Create( ' Config.json ' );
MyConfig.Provider.CreateIfNotExists := True;
MyConfig.Provider.ReloadIfFileModified := True;
MyConfig. Name := ' John ' ;
MyConfig.Surname := ' Smith ' ;
// load
MyConfig.Load;
// save
MyConfig.Save;
// create your config to Windows Registry
// Add Quick.Config.Registry to your uses
MyConfig := TMyConfig.Create;
// Define Registry as HKEY_CURRENT_USERSoftwareMyApp
MyConfig.HRoot := HKEY_CURRENT_USER;
MyConfig.MainKey := ' MyApp ' ;
MyConfig. Name := ' John ' ;
MyConfig.Surname := ' Smith ' ;
// load
MyConfig.Load;
// save
MyConfig.Save;
// Create a custom Config with no default provider
TMyConfig = class (TAppConfig)
...your properties
end ;
MyConfig := TMyConfig.Create(TAppConfigJsonProvider.Create( ' .config.json ' );
Мониторирует файл на предмет изменений и бросает события.
FileMonitor.Filename := ' .myfile.txt ' ;
// check file changes every 2 seconds
FileMonitor.Interval := 2000 ;
// watch for deleted or modified file events
FileMonitor.Notifies := [mnFileModified, mnFileDeleted)];
FileMonitor.OnFileChange := MyFileChangeFunction;
FileMonitor.Enabled := True;Utils для работы с объектами JSON.
// When unit declared in uses, a TObject Helper allows all your objects to be loaded or saved to/from json string
MyObject.FromJson := jsonstring;
MyString := MyObject.ToJson;
// You can clone simple objects with clone function
MyObject1.Clone(MyObject2);Отправьте электронное письмо с двумя строками кода.
// Send email
SMTP := TSMTP.Create( ' mail.domain.com ' , 25 ,False);
SMTP.SendMail( ' [email protected] ' , ' [email protected] ' , ' Email subject ' , ' My message body ' );
// You can define more advanced options
SMTP.SenderName := ' John ' ;
SMTP.From := ' [email protected] ' ;
SMTP.Recipient := ' [email protected],[email protected] ' ;
SMTP.Subject := ' Email subject ' ;
SMTP.AddBodyFromFile := ' .body.html ' ;
SMTP.CC := ' [email protected] ' ;
SMTP.BCC := ' [email protected] ' ;
SMTP.Attachments.Add( ' .notes.txt ' );
SMTP.SendMail;БЕЗОПАСНЫЕ КЛАССЫ.
TthreadedQueuecs: версия tthreadedqueue с критическим разделом.
TthreadObjectList: список безопасных объектов потока.
TthreadedQueuelist: список безопасных очередей. Автограмма и с критическим разделом.
TanonymousThread: создает анонимный поток, определяющий невыполненные методы выполнения и непрерывного. Используйте методы execute_sync и onterminate_sync, если код должен обновить пользовательский интерфейс.
// simple anonymousthread
TAnonymousThread.Execute(
procedure
var
i : Integer;
begin
for i := 0 to 10 do cout( ' Working %d ' ,[i],etTrace);
cout( ' executed thread ' ,etSuccess);
end )
.OnTerminate(
procedure
begin
cout( ' terminated thread ' ,etSuccess);
cout( ' PRESS <ENTER> TO EXIT ' ,etInfo);
end )
.Start;Truntask: запустите систему автоматической задачи с политиками управления неисправностью и повторной попытки. Парамы могут быть переданы и созданы в код.
TRunTask.Execute(
procedure(task : ITask)
var
stream : TStringStream;
response : IHttpRequestResponse;
begin
stream := TStringStream.Create;
try
response := TJsonHttpClient(task[ ' httpclient ' ].AsObject).Get(task[ ' url ' ]);
task.Result := response.StatusCode;
if response.StatusCode <> 200 then raise Exception.Create(response.StatusText);
finally
stream.Free;
end ;
end )
.SetParameter( ' httpclient ' ,(TJsonHttpClient.Create),True)
.SetParameter( ' url ' , ' https://mydomain.com/testfile ' )
.WaitAndRetry( 5 , 250 , 2 )
.OnRetry(
procedure(task : ITask; aException : Exception; var vStopRetries : Boolean)
begin
// if error 404 don't try to retry request
if task.Result = 404 then vStopRetries := True;
end )
.OnException(
procedure(task : ITask; aException : Exception)
begin
coutFmt( ' Exception downloading (Error: %s / StatusCode: %d)... ' ,[aException.Message,task.Result.AsInteger],etError);
end )
.OnTerminated(
procedure(task : ITask)
begin
if task.Done then coutFmt( ' Download "%s" finished ok ' ,[task[ ' url ' ].AsString],etSuccess)
else coutFmt( ' Download "%s" failed after %d retries ' ,[task[ ' url ' ].AsString,task.NumRetries],etError);
end )
.Run;TbackgroundStasks: Запуск задач в фоновом режиме, позволяя количествоми одновременных работников с политикой контроля ошибки и повторения. Используйте методы addtask_sync и onterminate_sync, если код должен обновить пользовательский интерфейс.
backgroundtasks := TBackgroundTasks.Create( 10 );
for i := 1 to 100 do
begin
mytask := TMyTask.Create;
mytask.Id := i;
mytask. Name := ' Task ' + i.ToString;
backgroundtasks.AddTask([mytask],False,
procedure(task : ITask)
begin
cout( ' task %d started ' ,[TMyTask(task.Param[ 0 ].AsObject).Id],etDebug);
TMyTask(task.Param[ 0 ].AsObject).DoJob;
end
).WaitAndRetry([ 250 , 2000 , 10000 ])
).OnException(
procedure(task : ITask; aException : Exception)
begin
cout( ' task %d failed (%s) ' ,[TMyTask(task.Param[ 0 ].AsObject).Id,aException.Message],etError);
end
).OnTerminated(
procedure(task : ITask)
begin
cout( ' task %d finished ' ,[TMyTask(task.Param[ 0 ].AsObject).Id],etDebug);
TMyTask(task.Param[ 0 ].AsObject).Free;
end
).Run;
end ;
backgroundtasks.Start;Tscheduledtasks: альтернатива таймеру. Вы можете назначить задачи со временем начала, параметров повторения и даты истечения срока действия, а также сбой и повторно контролируют политики. Используйте addtask_sync, onterminate_sync и onexpired_sync, если код должен обновить пользовательский интерфейс. Вы можете назначить анонимные методы для выполнения, исключения, завершения и истечения срока действия событий.
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;Управляет потерей и повторной политикой, определяя Макс -рис, время ожидания между повторными переписками и меканизмом.
Управляет процессами Windows.
// kill explorer process
KillProcess( ' explorer.exe ' );
// determine if an application is running
if IsProcessRunning( ' explorer.exe ' ) then Showmessage( ' Explorer is running! ' );
// get username who is running an exe
writeln( ' Explorer.exe open by: ' + GetProcessUser( ' explorer.exe ' );
// gets handle of a window with a 20 seconds timeout
if FindWindowTimeout( ' MainWindow ' , 20 ) then writeln( ' Window detected ' );Управляет службами Windows.
// detect if a service is installed
if not ServiceIsPresent( ' localhost ' , ' MySvc ' ) then raise Exception.Create( ' Service not installed! ' );
// Start a service
ServiceStart( ' localhost ' , ' MySvc ' );
// Uninstall a service
ServiceUninstall( ' MySvc ' );Строковой формат.
// Format bytes to MB, GB, TB...
FormatBytes( 50000 ) // shows 50KB
FormatBytes( 90000000 ) // shows 90MB Сериализует объект от/до текста JSON. Вы можете определить, будут ли обработаны публичные или опубликованные (только Delphi, FPC RTTI поддерживает только опубликованные свойства)
json := ' {"name":"Peter","age":30} ' ;
serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
try
serializer.JsonToObject(user,json);
finally
serializer.Free;
end ;Поля карты от одного класса в другой класс. Позволяет пользовательским сопоставлениям соответствовать различным полям и процедуре пользовательского сопоставления для съемки/конвертации полей вручную.
// Map values from User1 to User2
TMapper<TUser2>.Map(User);
// Map custom mappings
AutoMapper := TAutoMapper<TUser,TUser2>.Create;
// option1: you can define auto map different named properties
AutoMapper.CustomMapping.AddMap( ' Cash ' , ' Money ' );
AutoMapper.CustomMapping.AddMap( ' Id ' , ' IdUser ' );
// option2: you can decide to modify each property manually or allow to auto someones
AutoMapper.OnDoMapping := procedure( const aSrcObj : TUser; const aTargetName : string; out Value : TFlexValue)
begin
if aTargetName = ' Money ' then Value := aSrcObj.Cash * 2
else if aTargetName = ' IdUser ' then Value := aSrcObj.Id;
end ;
// option3: you can modify some properties after automapping done
AutoMapper.OnAfterMapping := procedure( const aSrcObj : TUser; aTgtObj : TUser2)
begin
aTgtObj.Money := aSrcObj.Cash * 2 ;
aTgtObj.IdUser := aSrcObj.Id;
end ;
User2 := AutoMapper.Map(User);Используется в качестве класса DTO, с функциями JSON Serialize и Mapping.
type
TUser = class (TJsonRecord)
private
fName : string;
fAge : Integer;
published
property Name : string read fName write fName;
property Age : Integer read fAge write fAge;
end ;
var
user, user2 : TUser;
begin
user := TUser.Create;
// show as json string
Writeln(user.ToJson);
// mapping to other class
user.Mapto(User2);
Writeln(user2.ToJson);
// load from file
user.LoadFromFile( ' .user.json ' );
// save to file
user2.SaveToFile( ' .user2.json ' );
end ;Улучшенные списки с индексацией или функциями поиска.
var
users : TIndexedObjectList<TUser>;
begin
users := TIndexedObjectList<TUser>.Create(True);
// create index by property "Name"
users.Indexes.Add( ' Name ' , ' Name ' ,TClassField.cfProperty);
// create index by private field "Id"
users.Indexes.Add( ' Id ' , ' fId ' ,TClassField.cfField);
// get user by "Name" index
writeln(users.Get( ' Name ' , ' Peter ' ).SurName);
end ;FlexValue сохраняет любой тип данных и позволяет передавать в другой класс с помощью интегрированных операторов и автофиров.
var
value : TFlexValue;
str : string;
num : Integer;
begin
value := ' hello ' ;
str := value ;
value := 123 ;
num := value ;
end ;Улучшенные массивы.
Txarray: массив с такими методами, как tlist.
var
users : TXArray<TUser>;
begin
users.Add(User);
if users.Count:= TIndexedObjectList<TUser>.Create(True);
// create index by property "Name"
users.Indexes.Add( ' Name ' , ' Name ' ,TClassField.cfProperty);
// create index by private field "Id"
users.Indexes.Add( ' Id ' , ' fId ' ,TClassField.cfField);
// get user by "Name" index
writeln(users.Get( ' Name ' , ' Peter ' ).SurName);
end ;TFLexArray: массив с такими методами, как TLIST, чем хранение различных типов значений в одном массиве.
var
flexarray : TFlexArray;
begin
flexarray.Add( 10 );
flexarray.Add( ' Hello ' );
user := TUser.Create;
try
user. Name := ' Joe ' ;
flexarray.Add(user);
cout( ' Integer Item = %d ' ,[flexarray[ 0 ].AsInteger],etInfo);
cout( ' String Item = %s ' ,[flexarray[ 1 ].AsString],etInfo);
cout( ' Record Item = %s ' ,[TUser(flexarray[ 2 ]). Name ],etInfo);
finally
user.Free;
end ;
end ;Tflexpairarray: массив с такими методами, как TLIST, чем можно хранить различные типы значений в одном массиве, и поиск по названию элемента.
var
flexarray : TFlexPairArray;
begin
flexarray.Add( ' onenumber ' , 10 );
flexarray.Add( ' other ' , ' Hello boy! ' );
user := TUser.Create;
try
user. Name := ' Joe ' ;
flexarray.Add( ' myuser ' ,user);
cout( ' Integer Item = %d ' ,[flexarray.GetValue( ' onenumber ' ).AsInteger],etInfo);
cout( ' String Item = %s ' ,[flexarray.GetValue( ' other ' ).AsString],etInfo);
cout( ' Record Item = %s ' ,[TUser(flexarray.GetValue( ' myuser ' )). Name ],etInfo);
finally
user.Free;
end ;
end ;Структура объекта YAML.
TyamLobject: объект YAML есть и массив пар YamlValue.
// create Yaml object from yaml text
yamlobj.ParseYamlValue(aYaml)
// add a pair
yamlobj.AddPair( ' Name ' , ' Mike ' );
// display as yaml structure
Writeln(yamlobj.ToYaml);Tyamlarray: множество объектов или скаляров.
yamlarray.AddElement(TYamlPair.Create( ' Age ' , 30 ));
yamlobj.AddPair( ' myarray ' ,yamlarray);Tyamlpair: пара имен-стоимость. Значение может быть объектом, массивом или скалярным.
n := yamlobj.GetPair( ' Name ' ). Value as TYamlInteger;Serialize/deserialize объект от/до YAML.
// Serialize
text := YamlSerializer.ObjectToYaml(obj);
// Deserialize
YamlSerializer.YamlToObject(obj,yamltext);Оценить свойства объекта или отдельные значения с использованием выражений.
if TExpressionParser.Validate(user,( ' (Age > 30) AND (Dept.Name = "Financial") ' ) then
begin
// do something
end ;
if TExpressionParser.Validate(user,( ' (20 > 30) OR (5 > 3) ' ) then
begin
// do something
end ;Задает LINQ запросы любому TobjectList, TLIST, Tarray и Txarray, выполняя Select By Complex, где, как и SQL Syntax, обновление и заказ по вашему списку. Где Clauses использует пространства имен для определения вложенных свойств. LINQ может искать элемент в массив свойств. Теперь включает в себя и вспомогательный Tarray для добавления, удаления и поиска с регулярными выражениями в массив.
// Select multi conditional
for user in TLinq<TUser>.From(userslist).Where( ' (Name = ?) OR (SurName = ?) OR (SurName = ?) ' ,[ ' Peter ' , ' Smith ' , ' Huan ' ]).Select do
begin
// do something
end ;
// Select like and update field
TLinq<TUser>.From(userlist).Where( ' SurName Like ? ' ,[ ' %son ' ]).SelectFirst. Name := ' Robert ' ;
// Select top and Order by field
for user in TLinq<TUser>.From(userlist).Where( ' Age > ? ' ,[ 18 ]).SelectTop( 10 ).OrderBy( ' Name ' ) do
begin
// do something
end ;
// update fields by conditional
TLinq<TUser>.From(userlist).Where( ' Name = ? ' ,[ ' Peter ' ]).Update([ ' Name ' ],[ ' Joe ' ]);
// count results
numusers := TLinq<TUser>.From(userlist).Where( ' (Age > ?) AND (Age < ?) ' ,[ 30 , 40 ]).Count;Tcustomhttpserver - это простой интерфейс, сдерживаемый httpserver с собственными реализациями Httprequest и Httpresponse, чтобы обеспечить легкие изменения двигателя httpserver. Вы можете включить пользовательские страницы ошибок для возврата настраиваемых страниц и динамических страниц ошибок. Thttpserver - это реализация Indyhttpserver, но вы можете определить свою собственную.
TMyHttpServer = class (THttpServer)
public
procedure ProcessRequest (aRequest: IHttpRequest; aResponse: IHttpResponse); override;
end ;
procedure TMyHttpServer.ProcessRequest (aRequest: IHttpRequest; aResponse: IHttpResponse);
begin
aResponse.ContentText := ' Hello world! ' ;
end ;CACHES объектов или строк со временем истечения, чтобы избежать генерирования этой информации каждый раз (запросы базы данных, трудно рассчитать информацию и т. Д.). TmemoryCache позволяет кэшировать объекты и строки. Общая версия TmemoryCache позволяет кэшировать только определенный тип.
// create MemoryCache with 10 seconds purge interval
cache := TMemoryCache.Create( 10 );
// create MemoryCache for a type
cache := TMemoryCache<TMyObj>.Create; // set string to cache without expiration
cache.SetValue( ' mystring ' , ' hello world ' );
// set string to cache with expiration to 10 seconds
cache.SetValue( ' mystring ' , ' this cache will expire in 10 seconds ' ;
// set object to cache
cache.SetValue( ' Obj1 ' ,valueobj); // get string query result
cache.GetValue( ' Query12 ' );
// get integer
cache.TryGetValue<Integer>( ' number ' ,valueint);
// get object
cache.TryGetValue( ' Obj1 ' ,valueobj);Удалить Value: удаляет объект из кеша.
Кэш -поставщики двигателей:
TcacheserializerJson: использует JSON для сериализации данных кэша.
Tcachecompressorgzip: использует Gzip для сжатия данных кэша.
Tcachecompressorlzo: использует LZO для сжатия данных кэша.
// create MemoryCache with 20 seconds purge interval and compression with LZO engine
cache := TMemoryCache.Create( 10 , nil ,TCacheCompressorLZO.Create);Инверсия диспетчера управления позволяет Autocreate Instanced Object или автоинсье в классах конструкторов, чтобы избежать зависимости.
Создайте контейнер для управления инъекцией зависимости.
iocContainer := TIocContainer.Create;Типы регистра:
Вам нужно зарегистрировать типы, прежде чем вы сможете вводить их. Тип может быть зарегистрирован как Синглтон, переход. Singleton : жизненный цикл будет одним экземпляром для всех инъекций, аналогично глобальной переменной. Переход : жизненный цикл будет один экземпляр на каждую инъекцию. Зарегистрируйте тип интерфейса в контейнер в качестве переходного процесса:
iocContainer.RegisterType<IMultService,TMultService>.AsTransient;Зарегистрируйте тип интерфейса как Singleton, делегируя конструкцию:
iocContainer.RegisterType<ISumService,TSumService>.AsSingleTon.DelegateTo(
function : TSumService
begin
Result := TSumService.Create;
end
);Зарегистрируйте экземпляры:
Зарегистрируйте названный объект экземпляра в качестве переходного, делегируя конструкцию:
iocContainer.RegisterInstance<TDivideService>( ' one ' ).AsTransient.DelegateTo(
function : TDivideService
begin
Result := TDivideService.Create(True);
end
);Параметры регистрации:
Зарегистрируйте ioptions (только Singleton):
iocContainer.RegisterOptions<TMyOptions>(MyOptions);Разрешение типов:
ABTRACTFACTORY: Создает класс, пытаясь разрешить все параметр метода создания с инъекцией зависимости.
MyClass := iocContainer.AbstractFactory<TMyBaseClass>(TMyClass);Установите зависимость от интерфейса:
multservice := iocContainer.Resolve<IMultService>;
result := multservice.Mult( 2 , 4 );Разрешить экземпляры:
Установите именованную зависимость экземпляра:
divideservice := iocContainer.Resolve<TDivideService>( ' other ' );
result := divideservice.Divide( 100 , 2 );Экземпляры интерфейса будут освобождены автоматически, но зависимости от экземпляров будут освобождены, только в том случае, если это будет определен как Синглтон, переходные экземпляры будут разрушены кодом.
Вы определяете разделы как классы и сохраняют в качестве единичных настройки. Работает аналогично параметрам Dotnet. Файл параметров может быть в формате JSON или YAML.
Определите свой класс опций, унаследованные от топов, и все опубликованные свойства будут загружены/сохранены. Создать контейнер с опциями, с Jsoneserializer и перезагрузку в изменениях:
Options := TOptionsContainer.Create( ' .options.conf ' ,TJsonOptionsSerializer.Create,True);Добавьте раздел в варианты контейнера:
Options.AddSection<TLoggingOptions>( ' Logging ' )Настройка параметров:
Вы можете определить имя раздела для сохранения в файле и делегировать настройки по умолчанию и проверки значений:
Options.AddSection<TLoggingOptions>( ' Logging ' ).ConfigureOptions(
procedure(aOptions : TLoggingOptions)
begin
aOptions.Path := ' C: ' ;
end
).ValidateOptions;Подтвердить варианты:
Параметры проверки позволяют проверить, установлены ли настройки опции между определенными диапазонами. Эта валидация требует ранее назначенных пользовательских атрибутов свойствам в вашем классе Toptions.
TLoggingOptions = class (TOptions)
private
fPath : string;
published
[Required, StringLength( 255 , ' Path too long ' )]
property Path : string read fPath write fPath;
[Range( 0.0 , 5.2 )]
property Level : Double read fLevel write fLevel;
end ;Используйте параметры: чтобы получить раздел опции:
LoggingOptions := Options.GetSection<TLoggingOptions>;
LoggginOptions.Path := ' C:Path ' ;Используйте ioptions: ioptions - это интерфейс, инъецируемый зависимостью, для топов. Вы можете зарегистрироваться в ioccontainer.registeroptions, чтобы сделать инъекцию в методы конструктора.
UIOptions := Options.GetSectionInterface<TUIOptions>. Value ;
UIOptions.WindowColor := clBlue;Загрузить/сохранить параметры:
Параметры загрузки из настройки файла:
options.Load;Сохранить параметры для настройки файла:
options.Save;Если вы определили создание контейнера с помощью параметра Reloadonchanged для true, каждый раз, когда настройки файла изменяются, конфигурация будет перезагружена. Если вам нужно контролировать, когда перезагрузить, вы можете прослушать событие:
Options.OnFileModified := procedure
begin
cout('Detected config file modification!',etWarning);
end;
Определите пул соединения, потоков или любого объекта, который вы хотите управлять, чтобы избежать потребления ресурсов, таких как подключения к базе данных, клиенты HTTP и т. Д.
Создайте HTTP Client Pool:
pool := TObjectPool<THTTPClient>.Create( 5 , 5000 ,procedure( var aInstance : THTTPClient)
begin
aInstance := THTTPClient.Create;
aInstante.UserAgent := ' MyAgent ' ;
end );Получить объект из бассейна:
httpcli := pool.Get.Item;
statuscode := httpcli.Get( ' https://www.mydomain.com ' ).StatusCode;Определяет интерфейс -список и объектный список с унаследованной поддержкой LINQ.
myarray := [ ' Joe ' , ' Mat ' , ' Lee ' ];
// search for regex match
cout( ' Search for regex match ' ,ccYellow);
for name in myarray.Where( ' e$ ' ,True).Select do
begin
cout( ' User %s ends with "e" ' ,[ name ],etInfo);
end ;user := ListObj.Where( ' Profile.Name = ? ' ,[ ' Lee ' ]).SelectFirst;Поиск выражения для массива элементов:
users := ListObj.Where( ' Roles CONTAINS ? ' ,[ ' SuperAdmin ' ]).Select;Поиск предиката:
user := ListObj.Where(function(aUser : TUser) : Boolean
begin
Result := aUser. Name .StartsWith( ' J ' );
end ).SelectFirst;
if user <> nil then cout( ' %s starts with J letter ' ,[user. Name ],etInfo);См. Раздел Quick.linq, чтобы просмотреть дополнительные функции, разрешенные.
Замена шаблона строки с использованием словаря или функции делегата. Вы можете указать цитируемые токеновые Chars.
Заменить прохождение словаря:
dict := TDictionary<string,string>.Create;
dict.Add( ' User ' , ' John ' );
dict.Add( ' Age ' , ' 20 ' );
dict.Add( ' SurName ' , ' Peterson ' );
mytemplate := ' User {{User}} {{SurName}} are {{Age}} years old. ' ;
template := TStringTemplate.Create( ' {{ ' , ' }} ' ,dict);
Result := template.Replace(mytemplate);Заменить функцией делегата:
mytemplate := ' User {{User}} {{SurName}} are {{Age}} years old. ' ;
template := TStringTemplate.Create( ' {{ ' , ' }} ' ,function( const aToken : string) : string
begin
if token = ' User ' then Result := ' John '
else if token = ' Surname ' then Result := ' Peterson '
else if token = ' Age ' then Result := ' 20 ' ;
end );
Result := template.Replace(mytemplate);Отладка UTILS для проверки производительности и получения Checkpoint Method Enter и Exit. Define с отладкой директивой компилятора, чтобы быть активным только тогда, когда ваше приложение будет скомпилировано в режиме отладки. На консольных приложениях используется консоль по умолчанию. Вы можете передать регистратор для вывода в:
TDebugUtils.SetLogger(ilogger);Проследить часть вашего кода:
function TCalculator.Subs (a, b: Int64): Int64;
begin
{ $IFDEF DEBUG }
TDebugger.Trace(Self,Format( ' Substract %d - %d ' ,[a,b]));
{ $ENDIF }
Result := a - b;
// simulate working for 200ms
Sleep( 200 );
end ;
// Returns:
// 29-06-2020 23:31:41.391 [TRACE] TCalculator -> Substract 30 - 12Рассчитайте время для обработки от точки к функции выхода:
function TCalculator.Sum (a, b: Int64): Int64;
begin
{ $IFDEF DEBUG }
TDebugger.TimeIt(Self, ' Sum ' ,Format( ' Sum %d + %d ' ,[a,b]));
{ $ENDIF }
Result := a + b;
// simulate working for 1 seconds
Sleep( 1000 );
end ;
// Returns:
// 29-06-2020 22:58:45.808 [CHRONO] TCalculator.Sum -> Sum 100 + 50 = 1,00sРассчитайте время для обработки из точки в точку и функции выхода:
function TCalculator.Divide (a, b: Int64): Double;
begin
{ $IFDEF DEBUG }
var crono := TDebugger.TimeIt(Self, ' Divide ' ,Format( ' Divide %d / %d ' ,[a,b]));
{ $ENDIF }
Result := a / b;
// simulate working for 500ms
Sleep( 500 );
{ $IFDEF DEBUG }
crono.BreakPoint( ' Only divide ' );
{ $ENDIF }
// simulate working for 1 second
Sleep( 1000 );
{ $IFDEF DEBUG }
crono.BreakPoint( ' Only Sleep ' );
{ $ENDIF }
end ;
// Returns:
// 29-06-2020 23:25:46.223 [CHRONO] TCalculator.Divide -> First point = 500,18ms
// 29-06-2020 23:25:47.224 [CHRONO] TCalculator.Divide -> Second point = 1,00s
// 29-06-2020 23:25:47.225 [CHRONO] TCalculator.Divide -> Divide 10 / 2 = 1,50sПолучите уведомление при введении и выходе в выход и времена:
function TCalculator.Mult (a, b: Int64): Int64;
begin
{ $IFDEF DEBUG }
TDebugger.Enter(Self, ' Mult ' ).TimeIt;
{ $ENDIF }
Result := a * b;
// simulate working for 2 seconds
Sleep( 2000 );
end ;
// Returns:
// 29-06-2020 22:58:45.808 [ENTER] >> TCalculator.Mult
// 29-06-2020 22:58:47.810 [EXIT] >> TCalculator.Mult in 2,00s Работа с параметрами командных линий будет легко с помощью расширения командной линии. Определите класс, унаследованный от Tparameters или TserviceParameters (при работе с QuickAppServices) с вашими возможными аргументами в качестве опубликованных свойств:
uses
Quick.Parameters;
type
TCommand = (Copy, Move, Remove);
TMyMode = (mdAdd, mdSelect, mdRemove);
[CommandDescription( ' Simple console application example with Quick.Parameters ' )]
TMyParameter = class (TParameters)
private
fCommand : TCommand;
fHost : string;
fPort : Integer;
fRetries : Integer;
fUseTCP : Boolean;
fConfigFile: string;
fSilent: Boolean;
fMyMode: TMyMode;
fLogErrorsConsole: Boolean;
fLogErrors: Boolean;
fShowReport: Boolean;
published
[ParamCommand( 1 )]
[ParamRequired]
[ParamHelp( ' Command action. ' , ' command-action ' )]
property Command : TCommand read fCommand write fCommand;
[ParamName( ' HostName ' ),ParamRequired]
[ParamHelp( ' Define host to connect. ' , ' host ' )]
property Host : string read fHost write fHost;
[ParamName( ' Port ' , ' p ' )]
[ParamValueIsNextParam]
[ParamHelp( ' Define Port to connect (default 80) ' , ' port ' )]
property Port : Integer read fPort write fPort;
[ParamHelp( ' Number of max retries. ' )]
property Retries : Integer read fRetries write fRetries;
[ParamHelp( ' Path to config. ' , ' path ' )]
[ParamName( ' Config-file ' )]
property ConfigFile : String read fConfigFile write fConfigFile;
[ParamHelp( ' Silent mode. ' )]
property Silent : Boolean read fSilent write fSilent;
[ParamHelp( ' Modes (mdAdd, mdSelect, mdRemove) ' )]
property Mode : TMyMode read fMyMode write fMyMode;
end ;
Используйте PARAM:
params := TMyParameter.Create;Когда вы звоните в свой exe с -вы получите документацию. Если вам нужно проверить на переключатель или значение, вы можете сделать это:
if params.Port = 0 then ...
if params.Silent then ...QuickParameters использует пользовательские атрибуты для определения специальных условий параметров:
CommandDescription: определяет текст для описания вашего приложения в документации по справочной службе.
ParamCommand (номер): определяет статическую позицию в командную линию для отдельных параметров.
ParamName (имя, псевдоним): определить различное имя для параметра. Позволяет использовать специальные символы, не разрешенные для свойств класса (например, файл name или config.file). Необязательный аргумент псевдонима определяет альтернативное (обычно короткое имя) имя параметра.
Paramhelp (elsextext, valueName): определяет текст справки командной линии и имя значения в разделе использования.
Paramswitchchar (знак): определяет строку или char, чтобы указать переключатель или параметр. Если не определено, двойная черта (-) будет использоваться по умолчанию.
ParamvalueSeparator (знак): определяет строку или char для отдельного имени параметра от значения (filename = config.json). Если не определено, равный знак (=) будет использоваться по умолчанию.
ParamvalueisnextParam: определяет параметр со значением без разделителя значения (имя файла c: config.ini)
ParamRequired: определяет параметр по мере необходимости. Если Param не найден, будет поднято исключение.
QuickParameter автоматически проверяет типы значений. Если вы определите значение параметра как целое число и пройдите альфанусую, будет поднято исключение.
Помощь настройки: вы можете определить свою собственную настройку цвета с помощью ColorizeHelp. Свойство с включенным будет использовать пользовательские цвета, в противном случае B/W будет использоваться.
Parameters.ColorizeHelp.Enabled := True;
Parameters.ColorizeHelp.CommandName := ccCyan;
Parameters.ColorizeHelp.CommandUsage := ccBlue;Когда параметры обнаруживают параметр справки, будет показана документация справки.
Parameters.showhelp: показывает документацию справки, сгенерированную автоматически:
Parameters v.1.0
Usage: Parameters <command-action> <--HostName=<host>> [--Port <port>] [--Retries=<value>]
[--Config-file=<path>] [--UseTCP] [--Silent] [--Mode=<value>]
[--ShowReport] [--Help]
Simple console application example with Quick.Parameters
Arguments:
Command Command action.
--HostName Define host to connect.
--Port, -p Define Port to connect (default 80)
--Retries Number of max retries.
--Config-file Path to config.
--UseTCP Use TCP connection if present.
--Silent Silent mode.
--Mode Modes (mdAdd, mdSelect, mdRemove)
--Help, -h Show this documentation
Обычно используются валидации.
PRE и пост -кондиционирование в стиле бегства. Condition.Requires оценивает переменную для условий, прежде чем выполнять некоторые операции. Условия.
Condition.Requires(num, " num " )
.IsInRange( 1 , 10 , ' value for num is out of range ' ); // throws custom error if not in range
.IsNotGreater( 50 ); // throws ArgumentException if not equal to 128
Condition.Requires(myobj, " myobj " )
.WithExceptionOnFailure(EMyException) // throws specific exception on failure
.IsNotNull() // throws ArgumentNullException if null
.Evaluate(myobj.id > 10 ); // myobj.id must be greater than 10
Condition.Requires(text, " text " )
.IsNotEmpty() // throws ArgumentNullException if empty
.StartsWith( " <html> " ) // throws ArgumentException if not starts with <html>
.EndsWith( " </html> " ) // throws ArgumentException if not ends with </html>
.IsNotLowerCase // thows ArgumentException if not lowercase
.Evaluate(text.Contains( " sometxt " ) or test.Contains( ' othertxt ' )); // throws ArgumentException if not evaluatesВы хотите изучить Delphi или улучшить свои навыки? LearnDelphi.org