"Unsatisfied constructor" 关于使用 Spring4D 进行构造函数注入

"Unsatisfied constructor" on constructor injection with Spring4D

我正在努力处理 Spring4D 的构造函数注入。在某个 class 中,我想将接口的特定实现(按名称)注入构造函数。

看看这个:

IListFactory = interface
    ['{40...29}']
    function GetList : IListOfSomething;
end;

ICiderPress = interface
    ['{50...10}']
    procedure Press;
end;

TAppleListFactory = class(TInterfacedObject, IListFactory)
    function GetList : IListOfSomething;
end;

TCiderPress = class(TInterfacedObject, ICiderPress)
private
    FListFactory : IListFactory;
public
    constructor Create(const ListFactory : IListFactory);

    procedure Press;
end;

implementation

function TCiderPress.Create(const ListFactory : IListFactory);
begin
    FListFactory := ListFactory;
end;

procedure TCiderPress.Press;
begin
    // Do somtihing with FListFactory
end;

initialization
    GlobalContainer.RegisterType<TAppleListFactory>.Implements<IListFactory>('apple');

    GlobalContainer.RegisterType<TCiderPress>.Implements<ICiderPress>;
end.

现在我使用 ServiceLocator 获得了我的印刷机实例:

CiderPress := ServiceLocator.GetService<ICiderPress>;
CiderPress.Press;

而且效果很好。

现在我添加第二个 ListFactory:

TOrangeListFactory = class(TInterfacedObject, IListFactory)
    function GetList : IListOfSomething;
end;

并添加注册

GlobalContainer.RegisterType<TOrangeListFactory>.Implements<IListFactory>('orange');

并将我的 cidre press class 更改为

TCiderPress = class(TInterfacedObject, ICiderPress)
private
    FListFactory : IListFactory;
public
    [Inject]
    constructor Create([Inject('apple')]const ListFactory : IListFactory);

    procedure Press;
end;

问题是,没有调用 TCiderPress 的构造函数。

如果我加上

GlobalContainer.AddExtension<TActivatorContainerExtension>;

我得到一个 EActivatorException:不满足类型的构造函数:TCiderPress

怎么了?

编辑:

它有效,如果我像这样委托构造:

GlobalContainer.RegisterType<TCiderPress>.Implements<ICiderPress>
    .DelegateTo(function : TCiderPress
        begin
            Result := TCiderPress.Create(ServiceLocator.GetService<IListFactory>('apple');
        end
    );

编辑2:

我发现了我的错误!我必须在接口 uses 子句中包含 Spring.Container.Common

我正在使用 Delphi XE3 和 Spring4D 1.1.3。

这对我有用:

unit Unit2;

interface

uses
  Spring.Container,
  Spring.Container.Common;

type
  IListOfSomething = interface
  ['{ACCEF350-5FDE-4D60-BAE0-17F029A669ED}']
  end;


  IListFactory = interface
  ['{039DE93A-1235-4D75-A8E2-7265765F6E90}']
    function GetList : IListOfSomething;
  end;

  ICiderPress = interface
  ['{64C4F565-BB8C-42C0-9584-4F4A21779F52}']
    procedure Press;
  end;

  TAppleListFactory = class(TInterfacedObject, IListFactory)
  public
    function GetList: IListOfSomething;
  end;

  TOrangeListFactory = class(TInterfacedObject, IListFactory)
  public
    function GetList: IListOfSomething;
  end;

  TCiderPress = class(TInterfacedObject, ICiderPress)
  private
    FListFactory: IListFactory;
  public
    [Inject]
    constructor Create([Inject('apple')] const ListFactory: IListFactory);
    procedure Press;
  end;

implementation

constructor TCiderPress.Create(const ListFactory: IListFactory);
begin
  FListFactory := ListFactory;
end;

procedure TCiderPress.Press;
begin
  WriteLn(TObject(FListFactory).ClassName);
end;

{ TAppleListFactory }

function TAppleListFactory.GetList: IListOfSomething;
begin
  Result := nil;
end;

{ TOrangeListFactory }

function TOrangeListFactory.GetList: IListOfSomething;
begin
  Result := nil;
end;

initialization
  GlobalContainer.RegisterType<TAppleListFactory>.Implements<IListFactory>('apple');
  GlobalContainer.RegisterType<TOrangeListFactory>.Implements<IListFactory>('orange');
  GlobalContainer.RegisterType<TCiderPress>.Implements<ICiderPress>;
  GlobalContainer.Build();
end.

并且喜欢

消费
o := GlobalContainer.Resolve<ICiderPress>;
o.Press();