1

使用 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.
4

1 回答 1

7

当您注册工厂时,您可以指定如何解析/匹配参数。默认情况下,这是按名称命名的,这意味着工厂方法中的参数用于查找匹配的构造函数。在您的情况下,IOrderShipperFactory它们与TOrderShipper构造函数上的参数相同。但在IDocumentFactory.Create它们与 上的那些并不相同TDocument.Create。您可以修复命名,也可以使用TParamResolution.ByValue它,然后在参数从工厂方法传入时传递参数,并在构造函数选择中按类型匹配它们。

于 2018-09-03T10:46:27.170 回答