我是Spring4D框架中的新手并请求帮助.
我有下一个类和接口:
ICommand = interface
TCommand = class(TInterfacedObject, ICommand)
IVecadCommand = interface(ICommand)
TVecadCommand = class(TCommand, IVecadCommand)
TVecadCommandJPG = class(TVecadCommand, IVecadCommand)
TCommandDeckelJPG = class(TVecadCommandJPG, IVecadCommand)
Run Code Online (Sandbox Code Playgroud)
然后我注册一个组件:
GlobalContainer.RegisterComponent<TCommandDeckelJPG>.Implements<IVecadCommand>('deckel_jpg');
Run Code Online (Sandbox Code Playgroud)
然后我尝试在ServiceLocator的帮助下创建一个对象:
var
i: Integer;
com: ICommand;
begin
Result := nil;
com := ServiceLocator.GetService<ICommand>(actionName);
com.setSession(designSession);
Result := com;
end;
Run Code Online (Sandbox Code Playgroud)
作为执行的结果,我有一个例外:
Invalid class typecast
Run Code Online (Sandbox Code Playgroud)
为了避免异常,我这样做:
var
i: Integer;
com: IVecadCommand;
begin
Result := nil;
com := ServiceLocator.GetService<IVecadCommand>(actionName);
com.setSession(designSession);
Result := com;
end;
Run Code Online (Sandbox Code Playgroud)
一切都好.
要点是我必须在这种情况下使用TContainer作为TCommand的Repository和继承的类.所以我必须先使用ServiceLocator.
我该怎么做才能避免异常并在TContainer中使用ICommand而不是IVecadCommand?
谢谢.将愉快地提供额外的细节.
你注册IVecadCommand
但要求ICommand
.
该错误具有误导性,实际上它应该引发一个异常,告诉你它不知道如何解决(似乎是一个错误 - 我会调查).
那是因为您只能要求明确注册的服务.它不会查找继承链.
如果您希望能够解决您的课程,则ICommand
需要.Implements<ICommand>
在注册时添加另一个课程.由于名称必须是唯一的,并且您可能希望按名称解析,因此您必须为其命名IVecadCommand
.如果你永远不想解决它IVecadCommand
(你可以在解决ICommand
之后使用支持),那么只需将现有注册更改IVecadCommand
为ICommand
.
编辑:
我实际上并不完全正确 - 当您按名称解析时,容器不会检查传递的类型.在这种情况下,问题是转换IVecadCommand
到ICommand
这是由完成TValue.AsType<T>
.但它没有正确处理.我将在即将发布的版本中解决这个问题.我只是不知道怎么样.为了保持一致性,这里的类型也应该严格.无论如何,如果你做了我上面所说的解决问题,你现在就安全了.
更新10.04.2014: 我已经解决了这个问题所以现在应该可以做一个命名解决方案来获取已解析的父接口.