【问题标题】:How to create inherited object using GlobalContainer (Spring4D framework) in Delphi?如何在 Delphi 中使用 GlobalContainer(Spring4D 框架)创建继承对象?
【发布时间】:2015-04-01 08:20:26
【问题描述】:

我在使用 Spring4D 框架的 GlobalContainer 创建从另一个继承的自定义类对象时遇到问题。

父类:

type
  TVSPSection = class ( TInterfacedObject, IVSPSection )

  private
        _id : Integer;
        _organization : IDirectoryObject;

        function GetId () : Integer;
        procedure SetId ( const value : Integer );
        function GetOrganization () : IDirectoryObject;
        procedure SetOrganization ( const value : IDirectoryObject );

  public
        property Id : Integer read GetId write SetId;
        property Organization : IDirectoryObject read GetOrganization write SetOrganization;

end;

...

initialization

  GlobalContainer.RegisterType<TVSPSection>.Implements<IVSPSection>.
        InjectField ( '_organization' )
        ;

后代类:

type
  TVSPSeismicSection = class ( TVSPSection, IVSPSeismicSection, IInterface )

  private
        _report : IReport;

        function GetReport () : IReport;
        procedure SetReport ( const value : IReport );

  public
        property Report : IReport read GetReport write SetReport;

end;

...

initialization

  GlobalContainer.RegisterType<TVSPSeismicSection>.Implements<IVSPSeismicSection>.
        InjectField ( '_report' )
        ;

end.

我尝试创建 TVSPSeismicSection 对象:

_seismicSection : IVSPSeismicSection;
_seismicSection := GlobalContainer.Resolve<IVSPSeismicSection>;

接下来,我尝试访问(父类的)“组织”字段并获得访问冲突错误。

 _seismicSection.Organization.Id := -1;    <- exception is here

那么,问题是如何告诉父类使用 GlobalContainer 解析器来启动它的字段?也许通过 DelegateTo 方法,但是如何?

我发现的一种方法是在后代类的构造函数中启动父字段,如下所示:

constructor TVSPSeismicSection.Create ();
begin

  Organization := GlobalContainer.Resolve<IDirectoryObject>;

end;

但这违反了依赖注入范式,因为我必须在后代类中包含其他类 (IDirectoryObject)。

【问题讨论】:

  • 尝试使用 _organization 字段上的 [Inject] 属性而不是调用 .InjectField (您需要将 Spring.Container.Common 添加到您的 uses 子句中)。否则显示你的接口的基本结构。使用 [inject] 属性对我来说效果很好,但不是你使用的 _InjectField
  • 感谢您的回答。是的,[inject] 属性是一个不错的功能,我已经尝试了很多次,但它对我不起作用。我不知道为什么,但是如果我使用此属性,我在具有此属性的字段中会出现访问冲突错误。这就是我使用 .InjectField 的原因。

标签: delphi inheritance spring4d


【解决方案1】:

有几种方法,这取决于哪种方法最好。 通常需要的依赖项应该作为构造函数参数传递,可选的依赖项应该通过属性注入传递。

因此,如果您将带有 IDirectoryObject 参数的构造函数添加到您的 TVSPSection 类,如果容器知道如何解析 IDirectoryObject,则它能够满足该参数。

这通常是最简洁的方式,因为关于使用 DI 容器的一条规则是编写仍然与 DI 容器无关的代码,并将容器仅用作工具而不是依赖项。

如果您想保留属性注入,那么在该属性上使用 Inject 属性应该可以工作(不要忘记将 Spring.Container.Common 添加到该属性的用途中),就像在注册中指定 InjectProperty 一样(如果可能我将避免字段注入,因为这只能通过 RTTI 而不是常规代码来实现 - 请参阅上一段)。

【讨论】:

  • 亲爱的 Stefan,感谢您的回答。是的,Inject 属性现在可以完美运行(我忘了 Spring.Container.Common)。
  • Stefan,我还要问你一个对象构造函数有一些参数和一些实现的情况。如何同时选择实现和传递参数?例如,GlobalContainer.Resolve&lt;IInterpretationProjectHelper&gt; ( [session] ); 其中session 是参数。那么,如何选择需要的实现呢?
  • 我不明白这个问题。我想这不应该在 cmets 中讨论。提出新问题或转到 Spring4D 小组(您可以在我们的项目页面上找到链接)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 2015-10-22
  • 1970-01-01
相关资源
最近更新 更多