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> 的实例,其中 TComponentTMyObject 构造函数接受的唯一参数。

作为从另一个 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;