4

我是 Spring4D 框架的新手,请帮助。

我有下一个类和接口:

ICommand = interface

TCommand = class(TInterfacedObject, ICommand)

IVecadCommand = interface(ICommand)

TVecadCommand = class(TCommand, IVecadCommand)

TVecadCommandJPG = class(TVecadCommand, IVecadCommand)

TCommandDeckelJPG = class(TVecadCommandJPG, IVecadCommand)

然后我注册一个组件:

GlobalContainer.RegisterComponent<TCommandDeckelJPG>.Implements<IVecadCommand>('deckel_jpg');

然后我尝试在 ServiceLocator 的帮助下创建一个对象:

var
  i: Integer;
  com: ICommand;
begin
  Result := nil;
  com := ServiceLocator.GetService<ICommand>(actionName);
  com.setSession(designSession);
  Result := com;
end;

作为执行的结果,我有一个例外:

Invalid class typecast

为了避免例外,我这样做:

var
  i: Integer;
  com: IVecadCommand;
begin
  Result := nil;
  com := ServiceLocator.GetService<IVecadCommand>(actionName);
  com.setSession(designSession);
  Result := com;
end;

然后一切正常。

重点是在这种情况下我必须使用它 TContainer 作为 TCommand 和继承类的存储库。所以我必须首先使用 ServiceLocator 。

我应该怎么做才能避免异常并在 TContainer 中使用 ICommand 而不是 IvecadCommand?

谢谢。将愉快地提供更多细节。

4

1 回答 1

6

您注册IVecadCommand但要求ICommand.

该错误具有误导性,实际上它应该引发一个异常,告诉您它不知道如何解决该错误(似乎是一个错误 - 我会调查)。

那是因为您只能请求您明确注册的服务。它不查找继承链。

如果您还希望能够解决您的课程,因为ICommand您需要.Implements<ICommand>在注册中添加另一个课程。由于名称必须是唯一的,并且您可能希望按名称解析,因此您必须给它一个不同于IVecadCommand. 如果您不想将其解析为IVecadCommand(您可以在解析为 后使用支持ICommand),那么只需将现有注册从 更改IVecadCommandICommand

编辑: 我实际上并不完全正确 - 当您按名称解析时,容器不会检查传递的类型。在这种情况下的问题是转换IVecadCommand为由. 但它不能正确处理。我会在即将发布的版本中解决这个问题。我只是还不知道怎么做。为了一致性,这里的类型也应该严格。无论如何,如果你按照我上面所说的来解决这个问题,你现在是安全的。ICommandTValue.AsType<T>

10.04.2014 更新: 我已经修复了这个问题,所以现在应该可以通过命名解析来取回已解析的父接口。

于 2014-04-01T00:11:02.160 回答