我刚刚开始使用Delphi Spring Framework,并想知道当前版本的DI容器是否允许将构造委托给工厂方法而不指定实现类型?
E.g。类似的东西:
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
实例化它们?
答案 0 :(得分:8)
不幸的是,弹簧DI容器的当前设计不允许这样做。它内部假定每种服务类型(通常是接口,但也可以是类)由组件类型(类)实现。因此,在这种情况下我们需要TObject
的几个地方IInterface
。就像传递给DelegateTo方法的委托一样,返回组件类型(或非泛型情况下的TObject)而不是服务类型。
这也是因为您可以在一个流畅的接口调用中注册一个具有多个接口实现的组件类型。像:
GlobalContainer
.RegisterType<TMyObject>
.Implements<IMyInterface>
.Implements<IMyOtherInterface>;
容器现在会检查TMyObject
是否与IMyInterface
和IMyOtherInterface
兼容。调用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>
添加其他接口,但与类不同,如果构造的实例实际上真的支持该接口,则在注册时将不会进行验证,因为它根本不可能。目前,在使用不受支持的服务类型调用nil
时,您将获得Resolve<T>
。它可能在将来引发例外。
答案 1 :(得分:1)
看起来Spring框架的体系结构目前不支持它,但它当然是可行的。在spring4d支持小组中已经suggested,并且对这个想法感兴趣。
TFactory
中有一个通用的Spring.DesignPatterns
类,可用于包裹CreateComObject/COCreateInstance
。