【问题标题】:How to get child interface instance from ServiceLocator in Spring4d?如何从 Spring4d 中的 ServiceLocator 获取子接口实例?
【发布时间】:2014-03-31 13:12:22
【问题描述】:

我是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?

谢谢。将很乐意提供更多详细信息。

【问题讨论】:

    标签: delphi spring4d


    【解决方案1】:

    您注册了IVecadCommand,但申请了ICommand

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

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

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

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

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

    【讨论】:

    • 是的,我找到了相同的解决方案。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 2017-01-10
    • 2016-10-27
    • 1970-01-01
    相关资源
    最近更新 更多