Spring4d:所有者自动出厂:TComponent参数?

时间:2015-12-15 04:05:05

标签: delphi dependency-injection spring4d

使用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>);

无需在容器中注册?

2 个答案:

答案 0 :(得分:0)

据我所知,如果没有注册,这是不可能的。

但是,使用来自IFactory<T,TResult>的不同Spring.Container.Common接口可以摆脱1-4参数的手动工厂实现,这将在注册时由DI容器自动实现。< / p>

所以你会这样注册:

aContainer.RegisterType<TMyObject>;
aContainer.RegisterType<IFactory<TComponent, TMyObject>>.AsFactory;

像这样注册工厂,不需要您的实施 - 容器将为您解决。

这意味着,只要您需要TMyObject的实例,就不再直接请求它(来自容器)。相反,您确实请求IFactory<TComponent, TMyObject>的实例,其中TComponentTMyObject构造函数接受的唯一参数。

作为使用另一个类TSomeClass的构造函数注入的用法的示例,(其中TSomeClass也是TComponent后代),它将如下所示:

constructor TSomeClass.Create(const AMyObjectFactory: IFactory<TComponent, TMyObject>);
begin
  fMyObjectInstance := AMyObjectFactory(Self);
end;

至少对我来说,这让事情变得更容易。

答案 1 :(得分:0)

如果我理解正确,你会试着避免这样的常规代码:

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 定义帮助程序类,它将为您创建结构,因此您编写的代码将是这样的:

aContainer.RegisterComponentDescendant<TMyFirstObject>;
aContainer.RegisterComponentDescendant<TMySecondObject>;
aContainer.RegisterComponentDescendant<TMyThirdObject>;

并像以前一样做。 Helper类的定义如下:

  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;