O aspecto4delphi consiste em uma biblioteca que permite o uso do conceito de programação orientada a aspectos (AOP) em Delphi.
AOP é um paradigma de programação que visa aumentar a modularidade, permitindo a separação de preocupações cruzadas. Faz isso adicionando comportamento adicional ao código existente sem modificação do próprio código. Em vez disso, podemos declarar esse novo código e esses novos comportamentos separadamente.
Aspect4Delphi nos ajuda a implementar essas preocupações cruzadas.
Para colocar uma cópia local em funcionamento, siga estas etapas simples.
Para usar esta biblioteca, é necessária uma versão atualizada do Delphi IDE (XE ou superior).
Clone o repo
git clone https://github.com/ezequieljuliano/Aspect4Delphi.git
Adicione o "caminho de pesquisa" do seu IDE ou do seu projeto os seguintes diretórios:
Aspect4Delphisrc
Para fornecer o paradigma de orientação do aspecto em seu projeto com ascest4delphi, você precisa:
Para ilustrar o uso, vejamos uma solução para gerenciar logs de um aplicativo.
Implementar um atributo Pointcut (preferencialmente herda do AspectAttribute):
interface
uses
Aspect.Core;
type
LoggingAttribute = class(AspectAttribute)
private
{ private declarations }
protected
{ protected declarations }
public
{ public declarations }
end;
implementation
end.
Implementar a classe que representa seu aspecto e contém os métodos de conselhos (você deve implementar a interface do IASPECT):
interface
uses
System.SysUtils,
System.Rtti,
Aspect,
Aspect.Core,
Logging.Attribute,
App.Context;
type
ELoggingAspectException = class(Exception)
private
{ private declarations }
protected
{ protected declarations }
public
{ public declarations }
end;
TLoggingAspect = class(TAspectObject, IAspect)
private
{ private declarations }
protected
procedure OnBefore(
instance: TObject;
method: TRttiMethod;
const args: TArray<TValue>;
out invoke: Boolean;
out result: TValue
); override;
procedure OnAfter(
instance: TObject;
method: TRttiMethod;
const args: TArray<TValue>;
var result: TValue
); override;
procedure OnException(
instance: TObject;
method: TRttiMethod;
const args: TArray<TValue>;
out raiseException: Boolean;
theException: Exception;
out result: TValue
); override;
public
{ public declarations }
end;
implementation
{ TLoggingAspect }
procedure TLoggingAspect.OnAfter(instance: TObject; method: TRttiMethod;
const args: TArray<TValue>; var result: TValue);
var
attribute: TCustomAttribute;
begin
inherited;
for attribute in method.GetAttributes do
if attribute is LoggingAttribute then
begin
LoggingFile.Add('After the execution of ' +
instance.QualifiedClassName + ' - ' +
method.Name
);
Break;
end;
end;
procedure TLoggingAspect.OnBefore(instance: TObject; method: TRttiMethod;
const args: TArray<TValue>; out invoke: Boolean; out result: TValue);
var
attribute: TCustomAttribute;
begin
inherited;
for attribute in method.GetAttributes do
if attribute is LoggingAttribute then
begin
LoggingFile.Add('Before the execution of ' +
instance.QualifiedClassName + ' - ' +
method.Name
);
Break;
end;
end;
procedure TLoggingAspect.OnException(instance: TObject; method: TRttiMethod;
const args: TArray<TValue>; out raiseException: Boolean;
theException: Exception; out result: TValue);
var
attribute: TCustomAttribute;
begin
inherited;
for attribute in method.GetAttributes do
if attribute is LoggingAttribute then
begin
LoggingFile.Add('Exception in executing ' +
instance.QualifiedClassName + ' - ' +
method.Name + ' - ' +
theException.Message
);
Break;
end;
end;
end.
Registre seu atributo Pointcut e sua classe de aspecto no contexto (de preferência mantenha esse contexto na instância de Singleton):
interface
uses
Logging.Aspect;
Aspect.Context;
function AspectContext: IAspectContext;
implementation
var
AspectContextInstance: IAspectContext = nil;
function AspectContext: IAspectContext;
begin
if (AspectContextInstance = nil) then
begin
AspectContextInstance := TAspectContext.Create;
AspectContextInstance.RegisterAspect(TLoggingAspect.Create);
end;
Result := AspectContextInstance;
end;
end.
Na sua classe de regra de negócios, use o atributo para definir seus pontos de junção. Você pode usar o construtor e o destruidor para adicionar sua classe no tecelão.
interface
uses
System.SysUtils,
Logging.Attribute,
App.Context;
type
EWhatsAppMessageException = class(Exception)
private
{ private declarations }
protected
{ protected declarations }
public
{ public declarations }
end;
TWhatsAppMessage = class
private
{ private declarations }
protected
{ protected declarations }
public
constructor Create;
destructor Destroy; override;
[Logging]
procedure Send; virtual;
end;
implementation
{ TWhatsAppMessage }
constructor TWhatsAppMessage.Create;
begin
inherited Create;
AspectContext.Weaver.Proxify(Self);
end;
destructor TWhatsAppMessage.Destroy;
begin
AspectContext.Weaver.Unproxify(Self);
inherited Destroy;
end;
procedure TWhatsAppMessage.Send;
begin
//Execution of send.
end;
Veja os problemas abertos para uma lista dos recursos propostos (e problemas conhecidos).
As contribuições são o que tornam a comunidade de código aberto um lugar tão incrível para aprender, inspirar e criar. Quaisquer contribuições que você faz são muito apreciadas .
git checkout -b feature/AmazingFeature )git commit -m 'Add some AmazingFeature' )git push origin feature/AmazingFeature ) Distribuído sob a licença Apache. Consulte LICENSE para obter mais informações.
Para entrar em contato conosco, use as opções:
https://github.com/ezequieljuliano/aspect4delphi