Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How does the Spring4D [inject]-Attribute function internally?

I’m trying to create a minimal example, that does the same thing as the Spring4D [inject] Attribute.
It’s supposed to automatically resolve my FDetailsAdapter in my TOrderAdapter, which I want to manually instantiate inside a Factory unit (not like the Spring4D container works, Registering interfaces from the outside first). The Factory should hand out any desired interfaces requested with [inject].

It is pretty obvious, that the code I have can not work (TOrderAdapter.FDetailsAdapter not being injected, giving me a nil pointer Access Violation on ButtonClick, the first use).
Reading through the Spring4D Source, I fail to see where this logical piece is, that I’m missing for the desired functionality to work in my example.

program OrderDetails;

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

The container uses RTTI to collect the members that have this attribute and injects the correct services into them.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading