"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();
我正在努力处理 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();