问题描述
我刚刚开始使用Delphi Spring框架,并且想知道当前版本的DI容器是否允许将构造委托给工厂方法而不指定实现类型?
例如类似于以下内容:
GlobalContainer
.RegisterFactory< ISomeObject>(
function:ISomeObject
begin
结果:= CreateComObject(CLASS_SomeObject)as ISomeObject;
end)
.Implements< ISomeObject> //可能是从上面的
隐含的.AsSingletonPerThread;
如你所见,我的具体用例是COM对象的实例化。在这种情况下,实现我感兴趣的接口的类不是我的应用程序的一部分,但我仍然能够通过调用 CreateComObject
/ CoCreateInstance
。但是,似乎我没有运气,因为容器中的注册总是看起来是绑定到一个实际的实现类。
假设这是不可能的那一刻,你们专家怎么会解决这个问题?你可以创建一个包装器类或者伪类,或者你只需将COM对象保存在DI容器中,然后通过 CreateComObject
?
不幸的是,当前设计的弹簧DI容器不允许。它在内部假定每个服务类型(通常是接口,但也可以是一个类)由一个组件类型(一个类)实现。因此,在这种情况下,我们需要在 IInterface
的多个位置具有 TObject
与委托一样,你传递给DelegateTo方法返回组件类型(或非类属情况下的TObject)而不是服务类型。
这也是因为你可以在仅一个流式接口调用中注册具有多个接口实现的一个组件类型。像:
GlobalContainer
.RegisterType< TMyObject>
。实现< IMyInterface>
。实现< IMyOtherInterface> ;;
容器现在检查 TMyObject
是否兼容到 IMyInterface
和 IMyOtherInterface
。当调用 Resolve
时,服务解析器在实例上使用 GetInterface
来获取请求的接口引用。这一点以外的一切都是在一个对象引用上完成的。
由于我有一些DI容器的计划,在注册接口时不需要依赖于实现类
$ b $ b
由于r522可以通过以下方式注册接口类型:
GlobalContainer
注册类型; ISomeObject>
.DelegateTo(
function:ISomeObject
begin
结果:= CreateComObject(CLASS_SomeObject)as ISomeObject;
end)
.AsSingletonPerThread;
在此示例中,将注册 ISomeObject
服务以及具有它继承的GUID的任何接口。
此外,您可以通过调用 Implements
但不像类的不会在注册时验证,如果构造的实例实际上真正支持该接口,因为它根本不可能。目前,当使用不支持的服务类型调用 Resolve< T>
时,将会收到 nil
它可能会在将来引发例外。
I'm just getting started with the Delphi Spring Framework and was wondering whether the current version of the DI container somehow allows delegating the construction to a factory method without specifying an implementing type?
E.g. something similar to this:
GlobalContainer
.RegisterFactory<ISomeObject>(
function: ISomeObject
begin
Result := CreateComObject(CLASS_SomeObject) as ISomeObject;
end)
.Implements<ISomeObject> // could probably be implied from the above
.AsSingletonPerThread;
As you can see, my specific use case is the instantiation of COM objects. In that case the class implementing the interface I'm interested in is not part of my application but I am still able to create instances by calling CreateComObject
/ CoCreateInstance
. However, it seems I'm out of luck as registrations in the Container always appear to be bound to an actual implementing class.
Assuming this isn't possible as such at the moment, how would you experts out there address this? Would you create a wrapper class or dummy class or would you simply keep COM objects out of the DI container and simply instantiate them via CreateComObject
?
Unfortunately the current design of the spring DI container does not allow that. It internally assumes that every service type (usually interface, but can also be a class) is implemented by a component type (a class). Thus having TObject
at several places where we would need IInterface
in this case. Like the delegate you are passing to the DelegateTo method returns the component type (or TObject in the non generic case) and not the service type.
That is also because you can register one component type with multiple interface implementations in just one fluent interface call. Like:
GlobalContainer
.RegisterType<TMyObject>
.Implements<IMyInterface>
.Implements<IMyOtherInterface>;
The container now checks if TMyObject
is compatible to IMyInterface
and IMyOtherInterface
. When calling Resolve
the service resolver uses GetInterface
on the instance to get the requested interface reference. Everything beyond that point is done on an object reference.
Since I have some plans for the DI container that require not having a dependency on an implementing class when registering interfaces this issue will be addressed in the future but not anytime soon.
Update (08.11.2012):
Since r522 it is possible to register interface types in the following way:
GlobalContainer
.RegisterType<ISomeObject>
.DelegateTo(
function: ISomeObject
begin
Result := CreateComObject(CLASS_SomeObject) as ISomeObject;
end)
.AsSingletonPerThread;
In this example it will register ISomeObject
as service and any interface with a GUID it inherits from.
Additionally you can add other interfaces by calling Implements<T>
but unlike for classes there will be no validation at registration time if the constructed instance actually really supports that interface since it simply is not possible. Currently you will get nil
when calling Resolve<T>
with a non supported service type. It may raise an exception in the future.
这篇关于Delphi Spring DI:是否可以委托接口实例化而不使用实现类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!