Spring4d:带有 Owner 的自动工厂:TComponent 参数?
Spring4d : Automatic factory with Owner : TComponent parameter?
使用 Spring4d,您可以像这样注册自定义工厂
aContainer.RegisterInstance<TFunc<string, TMyObject>>(function(aName : string):TMyObject
begin
Result := TMyObject.Create(aName);
end);
以这种方式,我相信对于从 TComponent
继承的每个依赖项,想要传递所有者的人要么做
// Registrations
aContainer.RegisterInstance<TFunc<TComponent, TMyObject>>(function(Owner : TComponent):TMyObject
begin
Result := TMyObject.Create(Owner);
end);
// Then in code
constructor TMyClass.Create(aFctry : TFunc<TComponent, TMyObject>);
begin
fObj := aFctry(Self);
end;
或者也可以
aContainer.RegisterType<TMyObject, TMyObject>;
// In code
constructor TMyClass.Create(aObj : TMyObject);
begin
fObj := aObj;
InsertComponent(aObj);
end;
不过,这很容易出错/添加代码只是为了传递所有者。是否有一种内置的方法可以让工厂将 TComponent 作为参数,而无需事先在容器中注册它?
因为我经常会用到
constructor MyObject.Create(aDep : TFunc<TMyDep>);
不注册TFunc<TMyDep>
依赖,只注册TMyDep
类型
是否可以传递类似
的内容
constructor MyObject.Create(aDep : TFunc<TComponent, TMyDep>);
无需在容器中注册?
据我所知,不注册是不可能的。
但是,有一种方法可以使用来自 Spring.Container.Common
的不同 IFactory<T,TResult>
接口摆脱 1-4 个参数的手动工厂实现,这将在注册时由 DI 容器自动实现.
所以你可以这样注册:
aContainer.RegisterType<TMyObject>;
aContainer.RegisterType<IFactory<TComponent, TMyObject>>.AsFactory;
像这样注册工厂,不需要在你这边实现——容器会为你解决。
这意味着,无论何时您需要 TMyObject
的实例,您都不再直接(从容器)请求它。相反,您确实请求 IFactory<TComponent, TMyObject>
的实例,其中 TComponent
是 TMyObject
构造函数接受的唯一参数。
作为从另一个 class TSomeClass
构造函数注入的用法示例(其中 TSomeClass
也是 TComponent
后代),它看起来如下所示:
constructor TSomeClass.Create(const AMyObjectFactory: IFactory<TComponent, TMyObject>);
begin
fMyObjectInstance := AMyObjectFactory(Self);
end;
至少对我来说,这让事情变得容易多了。
如果我没理解错的话,你尽量避免这样的例行代码:
aContainer.RegisterInstance<TFunc<TComponent, TMyFirstObject>>(function(Owner : TComponent):TMyFirstObject
begin
Result := TMyFirstObject.Create(Owner);
end);
aContainer.RegisterInstance<TFunc<TComponent, TMySecondObject>>(function(Owner : TComponent):TMySecondObject
begin
Result := TMySecondObject.Create(Owner);
end);
aContainer.RegisterInstance<TFunc<TComponent, TMyThirdObject>>(function(Owner : TComponent):TMyThirdObject
begin
Result := TMyThirdObject.Create(Owner);
end);
好吧,您可以使用过程 RegisterComponentDescendant 定义助手 class,这将为您创建结构,因此您编写的代码将像这样:
aContainer.RegisterComponentDescendant<TMyFirstObject>;
aContainer.RegisterComponentDescendant<TMySecondObject>;
aContainer.RegisterComponentDescendant<TMyThirdObject>;
和以前一样。 Helper class 定义如下:
TContainerHelper = class helper for TContainer
public
procedure RegisterComponentDescendant<TMyObject: TComponent>;
end;
及其实现:
procedure TContainerHelper.RegisterComponentDescendant <TMyObject>;
begin
self.RegisterInstance<TFunc<TComponent, TMyObject>>(
function(Owner : TComponent):TMyObject
begin
Result := TMyObject.Create(Owner);
end);
end;
使用 Spring4d,您可以像这样注册自定义工厂
aContainer.RegisterInstance<TFunc<string, TMyObject>>(function(aName : string):TMyObject
begin
Result := TMyObject.Create(aName);
end);
以这种方式,我相信对于从 TComponent
继承的每个依赖项,想要传递所有者的人要么做
// Registrations
aContainer.RegisterInstance<TFunc<TComponent, TMyObject>>(function(Owner : TComponent):TMyObject
begin
Result := TMyObject.Create(Owner);
end);
// Then in code
constructor TMyClass.Create(aFctry : TFunc<TComponent, TMyObject>);
begin
fObj := aFctry(Self);
end;
或者也可以
aContainer.RegisterType<TMyObject, TMyObject>;
// In code
constructor TMyClass.Create(aObj : TMyObject);
begin
fObj := aObj;
InsertComponent(aObj);
end;
不过,这很容易出错/添加代码只是为了传递所有者。是否有一种内置的方法可以让工厂将 TComponent 作为参数,而无需事先在容器中注册它?
因为我经常会用到
constructor MyObject.Create(aDep : TFunc<TMyDep>);
不注册TFunc<TMyDep>
依赖,只注册TMyDep
类型
是否可以传递类似
的内容constructor MyObject.Create(aDep : TFunc<TComponent, TMyDep>);
无需在容器中注册?
据我所知,不注册是不可能的。
但是,有一种方法可以使用来自 Spring.Container.Common
的不同 IFactory<T,TResult>
接口摆脱 1-4 个参数的手动工厂实现,这将在注册时由 DI 容器自动实现.
所以你可以这样注册:
aContainer.RegisterType<TMyObject>;
aContainer.RegisterType<IFactory<TComponent, TMyObject>>.AsFactory;
像这样注册工厂,不需要在你这边实现——容器会为你解决。
这意味着,无论何时您需要 TMyObject
的实例,您都不再直接(从容器)请求它。相反,您确实请求 IFactory<TComponent, TMyObject>
的实例,其中 TComponent
是 TMyObject
构造函数接受的唯一参数。
作为从另一个 class TSomeClass
构造函数注入的用法示例(其中 TSomeClass
也是 TComponent
后代),它看起来如下所示:
constructor TSomeClass.Create(const AMyObjectFactory: IFactory<TComponent, TMyObject>);
begin
fMyObjectInstance := AMyObjectFactory(Self);
end;
至少对我来说,这让事情变得容易多了。
如果我没理解错的话,你尽量避免这样的例行代码:
aContainer.RegisterInstance<TFunc<TComponent, TMyFirstObject>>(function(Owner : TComponent):TMyFirstObject
begin
Result := TMyFirstObject.Create(Owner);
end);
aContainer.RegisterInstance<TFunc<TComponent, TMySecondObject>>(function(Owner : TComponent):TMySecondObject
begin
Result := TMySecondObject.Create(Owner);
end);
aContainer.RegisterInstance<TFunc<TComponent, TMyThirdObject>>(function(Owner : TComponent):TMyThirdObject
begin
Result := TMyThirdObject.Create(Owner);
end);
好吧,您可以使用过程 RegisterComponentDescendant 定义助手 class,这将为您创建结构,因此您编写的代码将像这样:
aContainer.RegisterComponentDescendant<TMyFirstObject>;
aContainer.RegisterComponentDescendant<TMySecondObject>;
aContainer.RegisterComponentDescendant<TMyThirdObject>;
和以前一样。 Helper class 定义如下:
TContainerHelper = class helper for TContainer
public
procedure RegisterComponentDescendant<TMyObject: TComponent>;
end;
及其实现:
procedure TContainerHelper.RegisterComponentDescendant <TMyObject>;
begin
self.RegisterInstance<TFunc<TComponent, TMyObject>>(
function(Owner : TComponent):TMyObject
begin
Result := TMyObject.Create(Owner);
end);
end;