"不满意的构造函数"使用Spring4D进行构造函数注入

时间:2016-03-10 16:38:37

标签: delphi spring4d

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

看看这个:

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新闻课改为

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

    procedure Press;
end;

问题是,没有调用TCiderPress的ctor。

如果我添加

GlobalContainer.AddExtension<TActivatorContainerExtension>;

我收到EActivator异常:类型不满意的构造函数:TCiderPress

出了什么问题?

修改

如果我委托这样的结构:

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

EDIT2:

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

我使用的是Delphi XE3和Spring4D 1.1.3。

1 个答案:

答案 0 :(得分:5)

这对我有用:

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();