Delphi AOP和DI:如何创建方面感知接口依赖注入对象?
我想通过Spring/4D框架创建一个方面感知的接口依赖注入对象。我的问题是,我不知道如何将这两部分结合起来。总体思路如下:Delphi AOP和DI:如何创建方面感知接口依赖注入对象?,delphi,dependency-injection,aop,spring4d,Delphi,Dependency Injection,Aop,Spring4d,我想通过Spring/4D框架创建一个方面感知的接口依赖注入对象。我的问题是,我不知道如何将这两部分结合起来。总体思路如下: 创建aspect层对象并保留两个接口:一个作为依赖项传递给对象(iSpect),另一个作为aspect嵌入对象(IInterceptor): 创建接口依赖项注入对象: Instance := TInstance.Create(Aspect) {as IInstance}; 在这方面: Result := TProxyGenerator.CreateInterface
iSpect
),另一个作为aspect嵌入对象(IInterceptor
):
Instance := TInstance.Create(Aspect) {as IInstance};
Result := TProxyGenerator.CreateInterfaceProxyWithTarget(Instance, [Interceptor]);
Aspect := Resolve<IAspect>;
Interceptor := Aspect as IInterceptor;
Instance := InstanceFactory(Aspect); // InstanceFactory := Resolve<IInstanceFactory>;
Result := TProxyGenerator.CreateInterfaceProxyWithTarget(Instance, [Interceptor]);
输出:
Thingy1.Value: Value 1 intercepted by instance aspect 1 intercepted by class aspect
Thingy2.Value: Value 2 intercepted by instance aspect 2 intercepted by class aspect
Press enter...
我不完全确定您到底想要实现什么,但这里介绍了如何设置容器以获得您想要的结果。目前还不起作用的是上下文注入(在解析过程中根据当前构建的对象图做出决策)——这是我们计划在未来实现的
program Project1;
{$AppType Console}
{$R *.res}
uses
System.SysUtils,
Spring,
Spring.Container,
Spring.Interception;
type
IThingy = interface (IInvokable)
['{FD337CC6-03EB-4384-A027-E993AB687BF0}']
function GetValue: String;
procedure SetValue(const Value: String);
property Value: String read GetValue write SetValue;
end;
TThingy = class (TInterfacedObject, IThingy)
strict private
FValue: String;
function GetValue: String;
procedure SetValue(const Value: String);
end;
{ TThingy }
function TThingy.GetValue: String;
begin
Result := FValue;
end;
procedure TThingy.SetValue(const Value: String);
begin
FValue := Value;
end;
type
TClassInterceptor = class(TInterfacedObject, IInterceptor)
procedure Intercept(const Invocation: IInvocation);
end;
TInstanceInterceptor = class(TInterfacedObject, IInterceptor)
private
class var InstanceCount: Integer;
var FNo: Integer;
procedure Intercept(const Invocation: IInvocation);
public
constructor Create;
end;
{ Main }
procedure Main;
var
Thingy1: IThingy;
Thingy2: IThingy;
begin
GlobalContainer.RegisterType<TClassInterceptor,TClassInterceptor>.AsSingleton;
GlobalContainer.RegisterType<TInstanceInterceptor>('instance');
GlobalContainer.RegisterType<IThingy, TThingy>.InterceptedBy<TClassInterceptor>.InterceptedBy('instance');
GlobalContainer.Build;
Thingy1 := GlobalContainer.Resolve<IThingy>;
Thingy2 := GlobalContainer.Resolve<IThingy>;
Thingy1.Value := 'Value 1';
Thingy2.Value := 'Value 2';
WriteLn(Format('Thingy1.Value: %s', [Thingy1.Value]));
WriteLn(Format('Thingy2.Value: %s', [Thingy2.Value]));
end;
procedure TClassInterceptor.Intercept(const Invocation: IInvocation);
begin
Invocation.Proceed;
if Invocation.Method.Name = 'GetValue' then
Invocation.Result := TValue.From<String>(Invocation.Result.AsString + ' intercepted by class aspect');
end;
constructor TInstanceInterceptor.Create;
begin
Inc(InstanceCount);
FNo := InstanceCount;
end;
procedure TInstanceInterceptor.Intercept(const Invocation: IInvocation);
begin
Invocation.Proceed;
if Invocation.Method.Name = 'GetValue' then
Invocation.Result := TValue.From<String>(Invocation.Result.AsString + ' intercepted by instance aspect ' + IntToStr(FNo));
end;
begin
try
Main;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
if DebugHook <> 0 then
begin
WriteLn('Press enter...');
ReadLn;
end;
end.
程序项目1;
{$AppType控制台}
{$R*.res}
使用
System.SysUtils,
春天
弹簧,容器,
春天。拦截;
类型
i智能=接口(IInvokable)
[{FD337CC6-03EB-4384-A027-E993AB687BF0}]
函数GetValue:String;
过程设置值(常量值:字符串);
属性值:字符串读取GetValue写入SetValue;
结束;
t Thingy=类别(TInterfacedObject,i Thingy)
严格保密
FValue:String;
函数GetValue:String;
过程设置值(常量值:字符串);
结束;
{TThingy}
函数TThingy.GetValue:字符串;
开始
结果:=fv值;
结束;
过程TThingy.SetValue(常量值:字符串);
开始
FValue:=值;
结束;
类型
TClassInterceptor=类(TInterfacedObject,IIINTERCEPTOR)
过程截获(const调用:IInvocation);
结束;
TInstanceInterceptor=类(TInterfacedObject,IIInterceptor)
私有的
类var InstanceCount:整数;
var-FNo:整数;
过程截获(const调用:IInvocation);
公众的
构造函数创建;
结束;
{Main}
主程序;
变量
事情1:我想;
事情2:我想是的;
开始
GlobalContainer.RegisterType.AsSingleton;
RegisterType('instance');
GlobalContainer.RegisterType.InterceptedBy.InterceptedBy('instance');
环球集装箱。建造;
Thingy1:=全局容器。解析;
Thingy2:=GlobalContainer.Resolve;
Thingy1.值:='值1';
Thingy2.Value:=“值2”;
WriteLn(格式('Thingy1.Value:%s',[Thingy1.Value]);
WriteLn(格式('Thingy2.Value:%s',[Thingy2.Value]);
结束;
过程tclasinterceptor.Intercept(常量调用:IInvocation);
开始
调用。继续;
如果Invocation.Method.Name='GetValue',则
Invocation.Result:=TValue.From(Invocation.Result.AsString+‘被类方面截获’);
结束;
构造函数TInstanceInterceptor.Create;
开始
公司(InstanceCount);
FNo:=实例计数;
结束;
过程TInstanceInterceptor.Intercept(常量调用:IInvocation);
开始
调用。继续;
如果Invocation.Method.Name='GetValue',则
Invocation.Result:=TValue.From(Invocation.Result.AsString+'被实例方面截获'+IntToStr(FNo));
结束;
开始
尝试
主要的;
除了
关于E:Exception-do
WriteLn(E.ClassName,“:”,E.Message);
结束;
如果为0,则
开始
WriteLn('按enter…');
ReadLn;
结束;
结束。
Thingy1.Value: Value 1 intercepted by instance aspect 1 intercepted by class aspect
Thingy2.Value: Value 2 intercepted by instance aspect 2 intercepted by class aspect
Press enter...
program Project1;
{$AppType Console}
{$R *.res}
uses
System.SysUtils,
Spring,
Spring.Container,
Spring.Interception;
type
IThingy = interface (IInvokable)
['{FD337CC6-03EB-4384-A027-E993AB687BF0}']
function GetValue: String;
procedure SetValue(const Value: String);
property Value: String read GetValue write SetValue;
end;
TThingy = class (TInterfacedObject, IThingy)
strict private
FValue: String;
function GetValue: String;
procedure SetValue(const Value: String);
end;
{ TThingy }
function TThingy.GetValue: String;
begin
Result := FValue;
end;
procedure TThingy.SetValue(const Value: String);
begin
FValue := Value;
end;
type
TClassInterceptor = class(TInterfacedObject, IInterceptor)
procedure Intercept(const Invocation: IInvocation);
end;
TInstanceInterceptor = class(TInterfacedObject, IInterceptor)
private
class var InstanceCount: Integer;
var FNo: Integer;
procedure Intercept(const Invocation: IInvocation);
public
constructor Create;
end;
{ Main }
procedure Main;
var
Thingy1: IThingy;
Thingy2: IThingy;
begin
GlobalContainer.RegisterType<TClassInterceptor,TClassInterceptor>.AsSingleton;
GlobalContainer.RegisterType<TInstanceInterceptor>('instance');
GlobalContainer.RegisterType<IThingy, TThingy>.InterceptedBy<TClassInterceptor>.InterceptedBy('instance');
GlobalContainer.Build;
Thingy1 := GlobalContainer.Resolve<IThingy>;
Thingy2 := GlobalContainer.Resolve<IThingy>;
Thingy1.Value := 'Value 1';
Thingy2.Value := 'Value 2';
WriteLn(Format('Thingy1.Value: %s', [Thingy1.Value]));
WriteLn(Format('Thingy2.Value: %s', [Thingy2.Value]));
end;
procedure TClassInterceptor.Intercept(const Invocation: IInvocation);
begin
Invocation.Proceed;
if Invocation.Method.Name = 'GetValue' then
Invocation.Result := TValue.From<String>(Invocation.Result.AsString + ' intercepted by class aspect');
end;
constructor TInstanceInterceptor.Create;
begin
Inc(InstanceCount);
FNo := InstanceCount;
end;
procedure TInstanceInterceptor.Intercept(const Invocation: IInvocation);
begin
Invocation.Proceed;
if Invocation.Method.Name = 'GetValue' then
Invocation.Result := TValue.From<String>(Invocation.Result.AsString + ' intercepted by instance aspect ' + IntToStr(FNo));
end;
begin
try
Main;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
if DebugHook <> 0 then
begin
WriteLn('Press enter...');
ReadLn;
end;
end.