gpt4 book ai didi

delphi - AOP 和 DI : How to create an aspect-aware interfaced dependency-injected object?

转载 作者:行者123 更新时间:2023-12-03 18:35:22 25 4
gpt4 key购买 nike

我想通过 Spring/4D 框架的方式创建一个方面感知的接口(interface)依赖注入(inject)对象。我的问题是,我不知道如何将这两个部分结合起来。总体思路如下:

  • 创建方面层对象并持有两个接口(interface):一个作为对对象的依赖项( IAspect )和一个作为方面编织到对象中( IInterceptor ):
    Temp := TAspect.Create;
    Aspect := Temp as IAspect;
    Interceptor := Temp as IInterceptor;
  • 创建接口(interface)依赖注入(inject)对象:
    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]);

    我的问题是,我如何在 Container: TContainer 上注册它?从 Spring 开始?

    示例 :下面的程序表现得像我想要的那样,并演示了 GetValue 是通过哪个方面分层的。通话运行。自定义对象的创建发生在 $Region在主程序中。我需要如何重构这个程序以使用 Spring/4D 框架中的 DI 容器,同时保持一个方面感知对象的自定义构造?
    program Project1;

    {$AppType Console}

    {$R *.res}

    uses
    System.SysUtils,
    Spring,
    Spring.Interception;

    type
    IAspect = interface
    ['{AF8E19F6-176D-490E-A475-4682336CAB89}']
    function GetSetting: String;
    procedure SetSetting(const Value: String);

    property Setting: String read GetSetting write SetSetting;
    end;

    TAspect = class (TInterfacedObject, IInterceptor, IAspect)
    strict private
    FSetting: String;

    function GetSetting: String;
    procedure SetSetting(const Value: String);

    procedure Intercept(const Invocation: IInvocation);

    public
    constructor Create;
    end;

    IThingy = interface (IInvokable)
    function GetAspect: IAspect;
    function GetValue: String;
    procedure SetValue(const Value: String);

    property InstanceAspect: IAspect read GetAspect;
    property Value: String read GetValue write SetValue;
    end;

    TThingy = class (TInterfacedObject, IThingy)
    strict private
    FInstanceAspect: IAspect;
    FClassAspect: IAspect;
    FValue: String;

    function GetAspect: IAspect;
    function GetValue: String;
    procedure SetValue(const Value: String);

    public
    constructor Create(const InstanceAspect, ClassAspect: IAspect);
    end;

    { TAspect }

    constructor TAspect.Create;
    begin
    inherited;
    FSetting := ' intercepted by class aspect';
    end;

    function TAspect.GetSetting: String;
    begin
    Result := FSetting;
    end;

    procedure TAspect.Intercept(
    const Invocation: IInvocation);
    begin
    Invocation.Proceed;

    if Invocation.Method.Name = 'GetValue' then
    Invocation.Result := TValue.From<String>(Invocation.Result.AsString + FSetting);
    end;

    procedure TAspect.SetSetting(
    const Value: String);
    begin
    FSetting := Value;
    end;

    { TThingy }

    constructor TThingy.Create(const InstanceAspect, ClassAspect: IAspect);
    begin
    inherited Create;
    FInstanceAspect := InstanceAspect;
    FClassAspect := ClassAspect;
    FValue := 'Value';
    end;

    function TThingy.GetAspect: IAspect;
    begin
    Result := FInstanceAspect;
    end;

    function TThingy.GetValue: String;
    begin
    Result := FValue;
    end;

    procedure TThingy.SetValue(const Value: String);
    begin
    FValue := Value;
    end;

    { Main }

    procedure Main;
    var
    Temp: TInterfacedObject;
    ClassAspect: IAspect;
    ClassInterceptor: IInterceptor;
    InstanceAspect: IAspect;
    InstanceInterceptor: IInterceptor;
    Thingy1: IThingy;
    Thingy2: IThingy;
    begin
    {$Region 'How to do this with the Spring DI container?'}
    Temp := TAspect.Create;
    ClassAspect := Temp as IAspect;
    ClassInterceptor := Temp as IInterceptor;

    Temp := TAspect.Create;
    InstanceAspect := Temp as IAspect;
    InstanceInterceptor := Temp as IInterceptor;
    Thingy1 := TThingy.Create(InstanceAspect, ClassAspect);
    Thingy1 := TProxyGenerator.CreateInterfaceProxyWithTarget(Thingy1, [ClassInterceptor, InstanceInterceptor]);

    Temp := TAspect.Create;
    InstanceAspect := Temp as IAspect;
    InstanceInterceptor := Temp as IInterceptor;
    Thingy2 := TThingy.Create(InstanceAspect, ClassAspect);
    Thingy2 := TProxyGenerator.CreateInterfaceProxyWithTarget(Thingy2, [ClassInterceptor, InstanceInterceptor]);
    {$EndRegion}

    Thingy1.InstanceAspect.Setting := ' intercepted by instance aspect 1';
    Thingy2.InstanceAspect.Setting := ' intercepted by instance aspect 2';

    Thingy1.Value := 'Value 1';
    Thingy2.Value := 'Value 2';

    WriteLn(Format('Thingy1.Value: %s', [Thingy1.Value]));
    WriteLn(Format('Thingy2.Value: %s', [Thingy2.Value]));
    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.

    输出:
    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...

    最佳答案

    我不完全确定您到底要达到什么目的,但在这里它是如何设置容器以获得您正在寻找的结果。还不行的是上下文注入(inject)(在解析过程中基于当前构建的对象图做出决策)——这是我们计划在 future 实现的。

    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.

    关于delphi - AOP 和 DI : How to create an aspect-aware interfaced dependency-injected object?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37718563/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com