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。但是,似乎我不走运,因为 Container 中的注册似乎总是绑定到实际的实现类。

假设目前这是不可能的,那么你们那里的专家将如何解决这个问题?您会创建一个包装类或虚拟类,还是只是将 COM 对象排除在 DI 容器之外并简单地通过实例化它们CreateComObject

4

2 回答 2

9

不幸的是,spring DI 容器的当前设计不允许这样做。它在内部假设每个服务类型(通常是接口,但也可以是类)由组件类型(类)实现。因此,在这种情况下TObject,我们需要在几个地方。IInterface就像您传递给 DelegateTo 方法的委托一样,它返回组件类型(或非通用情况下的 TObject)而不是服务类型。

这也是因为您可以在一个流畅的接口调用中注册一种具有多个接口实现的组件类型。像:

GlobalContainer
  .RegisterType<TMyObject>
  .Implements<IMyInterface>
  .Implements<IMyOtherInterface>;

容器现在检查是否与和TMyObject兼容。在调用实例上的服务解析器时使用来获取请求的接口引用。超出该点的所有内容都在对象引用上完成。IMyInterfaceIMyOtherInterfaceResolveGetInterface

由于我对 DI 容器有一些计划,这些计划在注册接口时不需要依赖于实现类,这个问题将在未来得到解决,但不会很快解决。

更新(08.11.2012):

从 r522 开始,可以通过以下方式注册接口类型:

GlobalContainer
  .RegisterType<ISomeObject>
  .DelegateTo(
    function: ISomeObject 
    begin 
      Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end)
  .AsSingletonPerThread;

在此示例中,它将注册ISomeObject为服务和任何具有它继承的 GUID 的接口。

此外,您可以通过调用添加其他接口,Implements<T>但与类不同,如果构造的实例实际上确实支持该接口,则在注册时不会进行验证,因为这根本不可能。目前,当您使用不受支持的服务类型nil调用时,您会得到。Resolve<T>将来可能会引发异常。

于 2012-07-03T16:22:12.823 回答
1

看起来spring框架的架构目前不支持它,但它肯定是可行的。它已在 spring4d 支持小组中提出,并且对此想法很感兴趣。

有一个泛型TFactorySpring.DesignPatterns可以用于包装CreateComObject/COCreateInstance

于 2012-07-03T16:11:27.457 回答