Delphi Spring DI:是否可能在没有实现类型的情况下委托接口实例化?

8

我刚开始接触Delphi Spring Framework,想知道当前版本的DI容器是否允许委托构造工厂方法而不指定实现类型?

例如,类似于这样的方法:

GlobalContainer
  .RegisterFactory<ISomeObject>(
    function: ISomeObject 
    begin 
      Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end)
  .Implements<ISomeObject>  // could probably be implied from the above
  .AsSingletonPerThread;

如您所见,我的具体用例是实例化COM对象。在这种情况下,实现我感兴趣的接口的类不是我的应用程序的一部分,但我仍然可以通过调用CreateComObject / CoCreateInstance来创建实例。然而,似乎我没有运气,因为容器中的注册似乎总是绑定到一个实际的实现类。
假设目前不可能这样做,那么你们这些专家会如何解决这个问题?你们会创建一个包装类或虚拟类,还是只是将COM对象保持在DI容器之外,并通过CreateComObject来实例化它们?
2个回答

9
很遗憾,当前的Spring DI容器设计不允许这样做。它内部默认每个服务类型(通常是接口,但也可以是类)都由一个组件类型(一个类)实现。因此,在这种情况下,我们需要IInterface而不是在几个地方使用TObject。就像你传递给DelegateTo方法的委托返回组件类型(或在非泛型情况下为TObject),而不是服务类型。
这也是因为您可以在一个流畅的接口调用中注册一个组件类型并具有多个接口实现,例如:
GlobalContainer
  .RegisterType<TMyObject>
  .Implements<IMyInterface>
  .Implements<IMyOtherInterface>;

容器现在检查 TMyObject 是否与 IMyInterfaceIMyOtherInterface 兼容。调用 Resolve 时,服务解析器使用 GetInterface 在实例上获取所请求的接口引用。从那一点开始,所有操作都是在对象引用上完成的。
由于我对 DI 容器有一些计划,需要在注册接口时不依赖于实现类,因此这个问题将来会得到解决,但不会很快。
更新(08.11.2012):
自 r522 版本以来,可以按以下方式注册接口类型:
GlobalContainer
  .RegisterType<ISomeObject>
  .DelegateTo(
    function: ISomeObject 
    begin 
      Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end)
  .AsSingletonPerThread;

在这个例子中,它将会注册ISomeObject作为服务,并且还会注册任何从GUID继承而来的接口。
此外,您可以通过调用Implements<T>添加其他接口,但与类不同的是,在注册时不会验证构造的实例是否真正支持该接口,因为这是不可能的。目前,当使用不支持的服务类型调用Resolve<T>时,您将获得nil。未来可能会引发异常。

1

看起来Spring框架的架构目前不支持它,但这肯定是可行的。在spring4d支持组中已经建议过,并且对这个想法很感兴趣。

Spring.DesignPatterns中有一个通用的TFactory类,可能可以用来包装CreateComObject/COCreateInstance


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接