【问题标题】:How does the Spring4D [inject] attribute function internally?Spring4D [inject] 属性如何在内部起作用?
【发布时间】:2022-01-12 09:07:11
【问题描述】:

我正在尝试创建一个最小的示例,它与 Spring4D [inject] 属性执行相同的操作。它应该自动解析我的TOrderAdapter.FDetailsAdapter,我想在 Factory 单元内手动实例化它(不像 Spring4D 容器那样工作,首先从外部注册接口)。 工厂应该分发[inject]请求的任何所需接口。

很明显,我的代码无法工作(TOrderAdapter.FDetailsAdapter 没有被注入,给我一个nil 指针访问冲突ButtonClick,第一次使用)。通读 Spring4D 源代码,我看不到这个 逻辑部分 在哪里,我错过了,以便在我的示例中工作所需的功能。

program OrderDetails;

uses
  Vcl.Forms,
  Order.Adapter in 'Order.Adapter.pas',
  Details in 'Details.pas',
  Details.Adapter in 'Details.Adapter.pas',
  Factory.Adapter in 'Factory.Adapter.pas',
  Factory in 'Factory.pas',
  Order in 'Order.pas',
  Order.View in 'Order.View.pas' {OrderForm};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TOrderForm, OrderForm);
  Factory.Adapter.Factory := TFactoryAdapter.Create;
  Application.Run;
end.
unit Factory;

uses
  Rtti, TypInfo;

type
  InjectAttribute = class(TCustomAttribute)
  private
    fServiceType: PTypeInfo;
    fValue: TValue;
  public
    constructor Create(ServiceType: PTypeInfo); overload;
    property ServiceType: PTypeInfo read fServiceType;
    property Value: TValue read fValue;
  end;

implementation

constructor InjectAttribute.Create(ServiceType: PTypeInfo);
begin
  inherited Create;
  fServiceType := ServiceType;
end;

end.
unit Factory.Adapter;

uses
  Details, Details.Adapter, Order, Order.Adapter;

type
  TFactoryAdapter = class
  private
    FDetailsAdapter: IDetailsAdapter;
    FOrderAdapter: IOrderAdapter;
  public
    constructor Create;
    function Inject: IInterface; overload; // unused
  end;

var
  Factory: TFactoryAdapter;

implementation

constructor TFactoryAdapter.Create;
begin
  FDetailsAdapter := TDetailsAdapter.Create;
  FOrderAdapter := TOrderAdapter.Create;
end;

function TFactoryAdapter.Inject: IInterface; // unused
begin
  Result := FDetailsAdapter;
end;

end.
unit Details.Adapter;

uses
  Details, Winapi.Windows, SysUtils;

type
  TDetailsAdapter = class(TInterfacedObject, IDetailsAdapter)
  private
    FID: Integer;
  public
    procedure SetID(AID: Integer);
    function GetID: Integer;
  published
    property ID: Integer read GetID write SetID;
  end;

implementation

procedure TDetailsAdapter.SetID(AID: Integer);
begin
  FID := AID;
  OutputDebugString(PWideChar('OrderDetail ID set to ' + IntToStr(FID)));
end;

function TDetailsAdapter.GetID: Integer;
begin
  Result := FID;
end;

end.
unit Order.Adapter;

uses
  Order, Order.View, Details, Factory,
  Vcl.Forms;

type
  TOrderAdapter = class(TInterfacedObject, IOrderAdapter)
  private
    [inject]
    FDetailsAdapter: IDetailsAdapter;
  public
    constructor Create;
    procedure ButtonClick(Sender: TObject);
  end;

var
  OrderForm: TOrderForm;

implementation

constructor TOrderAdapter.Create;
begin
  OrderForm.Button1.OnClick := ButtonClick;
end;

procedure TOrderAdapter.ButtonClick(Sender: TObject);
begin
  FDetailsAdapter.ID := 5;
end;

end.

【问题讨论】:

    标签: delphi inject spring4d


    【解决方案1】:

    容器使用RTTI来收集具有该属性的成员,并为其注入正确的服务。

    【讨论】:

    • 所以我的 FDetailsAdapter: IDetailsAdapter;至少应该出版?这种注入魔法到底发生在 Spring4D 源代码的什么地方?
    • 我想我找到了一些东西:TPropertyInjection.DoInject。看起来我的示例缺少大量代码才能正常工作......我想我可以以某种方式跳过 [inject] 属性,但看起来这都是手动工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 2014-07-01
    • 1970-01-01
    • 2019-09-30
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多