Delphi Spring DI: Is it possible to delegate interface instantiation without an implementing type?

岁酱吖の 提交于 2019-12-04 11:27:03

问题


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?


回答1:


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.




回答2:


Doesn't look like the architecture of the spring framework currently supports it but its certainly feasible. It has been suggested in the spring4d support group and there is interest in the idea.

There is a generic TFactory class in Spring.DesignPatterns that may be of use in wrapping CreateComObject/COCreateInstance.



来源:https://stackoverflow.com/questions/11312357/delphi-spring-di-is-it-possible-to-delegate-interface-instantiation-without-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!