Spring4D:在创建时用所有者解析 TFrame

Spring4D: resolve a TFrame with owner in create

我注册了一些框架,例如:

GlobalContainer.RegisterType<TfraBasePage, TfraSetting>(IDSettingPage);
GlobalContainer.RegisterType<TfraBasePage, TfraCurrency>(IDCurrencyPage);
GlobalContainer.RegisterType<TfraBasePage, TfraTicketLayOut>(IDTicketLayOutPage);
GlobalContainer.RegisterType<TfraBasePage, TfraSetUp>(IDSetUpPage);

我可以这样调用框架:

  Result := GlobalContainer.Resolve<TfraBasePage>(aPageName); 

但是构造函数'create'所有者是nil。 如何传递所有者组件?

现在我在解决后用'InsertComponent'解决这个问题。

var
  oFrame: TfraBasePage;
begin
 oFrame:= GlobalContainer.Resolve<TfraBasePage>('SettingPage'); 
  if assigned(oFrame) then
  begin
    Self.InsertComponent(oFrame);
  end;

工厂也可以这样吗?

 TfraBasePage = class(TfraBase, IPage)
...

 TfraSetting = class(TfraBasePage)
...

 IPageFactory = interface(IInvokable)
  ['{2E40E3C4-87B7-4313-BE0A-29202B7EB5A1}']
    function Create(aOwner: TComponent): TfraBasePage;
  end;
...

GlobalContainer.RegisterFactory<IPageFactory>;
GlobalContainer.RegisterType<TfraBasePage, TfraSetting>('SettingPage');

...
var
  oFrame: TfraBasePage;
begin
 //Here I can't solve how to get the 'SettingPage' Frame with the factory.
 //I miss something, the ('SettingPage') is on the wrong place.
 oFrame:= GlobalContainer.Resolve<IPageFactory>('SettingPage').Create(Self); 


有两种可能的解决方案:

uses
  Classes,
  Spring.Container;

type
  TBaseFrame = class(TComponent) // just for testing a TComponent descendant
  end;

  TDemoFrame = class(TBaseFrame)
  end;

  TFrameFactory = reference to function(const serviceName: string; owner: TComponent): TBaseFrame;

procedure Main;
var
  owner: TComponent;
  frame: TBaseFrame;
  factory: TFrameFactory;
begin
  GlobalContainer.RegisterType<TBaseFrame, TDemoFrame>('myframe');
  GlobalContainer.Build;

  owner := TComponent.Create(nil);
  owner.Name := 'owner';

  // Possibility 1 - pass args to Resolve -
  // they will be matched via their type when looking for an appropriate ctor
  frame := GlobalContainer.Resolve<TBaseFrame>('myframe', [owner]);
  Writeln(frame.Owner.Name);

  // Possibility 2 - register a custom factory function -
  // RegisterFactory does not support passing the serviceName through the factory interface
  GlobalContainer.RegisterInstance<TFrameFactory>(
    function(const serviceName: string; owner: TComponent): TBaseFrame
    begin
      Result := GlobalContainer.Resolve<TBaseFrame>(serviceName, [owner]);
    end);
  GlobalContainer.Build;

  // don't forget the parentheses here else the compiler will barf 
  // because return type is something invokable
  factory := GlobalContainer.Resolve<TFrameFactory>(); 

  frame := factory('myframe', owner);
  Writeln(frame.Owner.Name);

  // yes, memoryleaks - demo code to answer the question
end;

begin
  Main;
  readln;
end.