Неудовлетворенный конструктор по типу - PullRequest
0 голосов
/ 03 сентября 2018

игра с использованием Dependency Injection Framework от 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.

1 Ответ

0 голосов
/ 03 сентября 2018

Когда вы регистрируете фабрику, вы можете указать, как параметры разрешаются / сопоставляются. По умолчанию это по имени, что означает, что параметры, входящие в метод фабрики, используются для поиска подходящего конструктора. В случае вашего IOrderShipperFactory они идентичны параметрам вашего TOrderShipper конструктора. Но в IDocumentFactory.Create они не идентичны тем, что в TDocument.Create. Вы можете либо исправить имя, либо использовать TParamResolution.ByValue, который затем просто пропускает параметры по мере их поступления из фабричного метода и сопоставляет их по типу при выборе конструктора.

...