0

假设,我有以下代码:

interface
        type 
          IMyInterface1 = interface // GUID
            procedure ButtonEvent(Sender: TObject);
          end;

          IMyInterface2 = interface // GUID
            procedure DoSomething;
          end;

          TMyClass1 = class(TInterfacedObject, IMyInterface1)
          public
            procedure ButtonEvent(Sender: TObject);
          end;

          TMyClass2 = class(TInterfacedObject, IMyInterface2)
          public 
            procedure DoSomething;
          end;

// ...
implementation        
        procedure TMyClass1.ButtonEvent(Sender: TObject);
        var
          aIntf2: TMyInterface2;
        begin
          // Pseudo code:
          // aIntf2 := ServiceLocator.GetService<IMyInterface2>;
          try
            aIntf2.DoSomething;
          finally
            aIntf2 := nil; // will free the instance...
          end;
        end;

    initialization
      // Pseudo code:
      // GlobalContainer register IMyInterface1 / TMyClass1
      // GlobalContainer register IMyInterface2 / TMyClass2
      // GlobalContainer.Build
    end.

方法 ButtonEvent 由 delphi 表单按钮单击事件调用。

现在我的问题是:有没有更好的方法来实例化 TMyClass2 类?在我的情况下,无法注入 TMyClass1 类,TMyClass2 实例的生命周期仅在 ButtonEvent 内。对 ButtonEvent 的下一次调用应该使用不同的实例......

AFAIK,方法参数注入或局部变量注入在 Spring4D 中是不可能的,是吗?

4

1 回答 1

2

如果你想避免可怕的服务定位器模式,它不能解决 DI 解决的问题,而只是改变它(或者在许多情况下甚至使事情变得更糟,因为你有伪解耦代码,它仍然有依赖关系,你只有在运行代码并确定您必须注册某种类型才能使服务定位器返回正确的内容)。

方法参数注入还是局部变量注入?这怎么可能。它需要对调用进行一些拦截,以便容器将某些东西注入寄存器/堆栈。

虽然某些方法(虚拟方法)可以进行拦截,但仍然需要为此设置被调用的实例。如果你这样做,你可以首先注入你的依赖。

如果你没有将 DI 放在你的组合根目录中,你总是必须在代码中使用某种服务定位器,从那里你想要开始依赖注入过程。

想想 DI,尤其是使用容器作为实现特定目标的工具:主要是为了各种好处将代码解耦。正如我所说,在这种情况下使用服务定位器可能会导致比它解决的问题更多的问题。

但是回到您的示例:这是使用工厂的经典案例。您需要将其注入您的 TMyClass1。然后它可以在您的方法中调用工厂并检索 IMyInterface2。根据您使用的 Spring4D 版本,容器可以通过不同的方式为您节省一些工作,因为它能够为您构建工厂。但我建议使用经典模式自己编写工厂。这样你才能体会到。稍后,当您对它的使用以及在哪里使用容器更有经验和信心时,可以轻松地接管该部分。

于 2015-05-01T16:13:22.433 回答