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.
我注册了一些框架,例如:
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.