使用Spring4D的依赖注入框架。
此刻,我尝试使用DynamicAbstractFactories。
测试中有2个班级和工厂:
IOrderShipper
和IOrderShipperFactory
可以使用,
IDocument
和IDocumentFactory
将失败。
过程TestDocument中的代码将引发
类型不满意的构造函数:DynamicAbstractFactory.TDocument
我不明白为什么... 我希望有人知道原因,我真的很傻
program DynamicAbstractFactory;
{$APPTYPE CONSOLE}
uses
System.Sysutils,
Spring.Container;
type
TEnum = (e1, e2, e3, e4, e5);
IDocument = interface
['{CCB718EF-7670-4157-97FF-0E49ACBEB449}']
procedure Show;
end;
IDocumentFactory = interface(IInvokable)
['{73ADE7C1-3119-45B6-B615-04A4079AA581}']
function Create: IDocument; overload;
function Create(ID: integer; DocType: TEnum; Level: integer): IDocument; overload;
end;
IOrderShipper = interface
['{F4653C0C-2C05-4348-A744-3288E520F586}']
procedure Ship;
end;
IOrderShipperFactory = interface(IInvokable)
['{F632D1FB-9C34-48FD-BD72-6BBC436D1B47}']
function Create: IOrderShipper; overload;
function Create(const name: string): IOrderShipper; overload;
function Create(aId: integer; en: TEnum; Level: integer): IOrderShipper; overload;
end;
TOrderShipper = class(TInterfacedObject, IOrderShipper)
private
fName: string;
public
constructor Create; overload;
constructor Create(const name: string); overload;
constructor Create(aId: integer; en: TEnum; Level: integer); overload;
procedure Ship;
end;
TDocument = class(TInterfacedObject, IDocument)
public
constructor Create; overload;
constructor Create(aId: integer; aDocType: TEnum; aLevel: integer); overload;
procedure Show;
end;
constructor TDocument.Create;
begin
inherited Create;
end;
constructor TDocument.Create(aId: integer; aDocType: TEnum; aLevel: integer);
begin
inherited Create;
end;
procedure TDocument.Show;
begin
writeln('Show Document');
end;
constructor TOrderShipper.Create;
begin
Create('default');
end;
constructor TOrderShipper.Create(const name: string);
begin
inherited Create;
fName := name
end;
constructor TOrderShipper.Create(aId: integer; en: TEnum; Level: integer);
begin
Create('Args Enum E'+ (ord(en)+1).ToString);
end;
procedure TOrderShipper.Ship;
begin
Writeln('shipped by: ', fName, ' ');
end;
procedure FillContainer;
begin
GlobalContainer.RegisterType<IOrderShipper, TOrderShipper>;
GlobalContainer.RegisterType<IOrderShipperFactory>.AsFactory;
GlobalContainer.RegisterType<IDocument, TDocument>;
GlobalContainer.RegisterType<IDocumentFactory>.AsFactory;
GlobalContainer.Build;
end;
procedure TestOrder;
var
factory: IOrderShipperFactory;
service: IOrderShipper;
begin
factory := GlobalContainer.Resolve<IOrderShipperFactory>;
service := factory.Create;
service.Ship;
service := factory.Create('Test');
service.Ship;
service := factory.Create(1, TEnum.e5, 3);
service.Ship;
end;
procedure TestDocument;
var
factory: IDocumentFactory;
service: IDocument;
begin
factory := GlobalContainer.Resolve<IDocumentFactory>;
service := factory.Create;
service.Show;
// This call will fail.........
service := factory.Create(1, TEnum.e5, 3);
service.Show;
end;
begin
ReportMemoryLeaksOnShutdown := True;
try
FillContainer;
try
TestOrder;
TestDocument;
except
on E: Exception do
writeln(E.message);
end;
finally
Readln;
end;
end.
答案 0 :(得分:7)
注册工厂时,可以指定参数的解析/匹配方式。默认情况下,这是名称,这意味着工厂方法中使用的参数用于查找匹配的构造函数。对于您的IOrderShipperFactory
,它们与TOrderShipper
构造函数上的参数相同。但是在IDocumentFactory.Create
中,它们与TDocument.Create
中的不相同。您可以修复命名,也可以使用TParamResolution.ByValue
,然后将其从工厂方法传入时直接传递给它们,并按构造函数选择中的类型进行匹配。