3

我正在为 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 press 课程更改为

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

    procedure Press;
end;

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

如果我添加

GlobalContainer.AddExtension<TActivatorContainerExtension>;

我得到一个 EActivatorException: Unsatisfied contructor on type: TCiderPress

怎么了?

编辑:

如果我像这样委托构造,它会起作用:

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

编辑2:

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

我正在使用 Delphi XE3 和 Spring4D 1.1.3。

4

1 回答 1

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();
于 2016-03-11T07:02:05.837 回答