如果不能解析所有参数,Spring4D 不应调用继承的构造函数

发布于 2025-01-13 01:29:05 字数 801 浏览 1 评论 0原文

我们使用 Spring4D 的依赖注入框架,如果它无法解析所有构造函数参数,那么它构造对象的方式就会出现问题。在我们的例子中,祖先构造函数的所有参数都可以解析,看起来 Spring4D 现在使用这个构造函数。即使我们重新引入后代的构造函数,它仍然使用祖先的构造函数。

但是,我期望(并且更喜欢)的行为是,如果无法为您尝试解析的接口找到正确的构造函数,则解析将失败。

示例:

TMyClass = class(TInterfacedObject, IMyClass)
  constructor Create(ARequester: IRequester);
end;

TMyDescendant = class(TMyClass, IMyDescendant)
  constructor Create(ARequester: IRequester; AnotherRequester: IOtherRequester);
end;

GlobalContainer.Resolve<IMyDescendant>

在此示例中,如果没有注册实现 IOtherRequester 的类,它将调用 TMyClass 的构造函数。这意味着 TMyDescendant 构造函数中的任何 Guard.IsNotNull 都不起作用,因为该构造函数从未被调用。

有办法解决这个问题吗?当然,我们可以重写TMyDescendantTMyClass的构造函数,但我更喜欢一种更简洁的方法来做到这一点。

We use the dependency injection framework from Spring4D and have an issue with the way it constructs objects if it cannot resolve all constructor parameters. In our case all parameters of the constructor of the ancestor can be resolved and it looks like that Spring4D now uses this constructor. Even if we reintroduce the constructor the descedant, it still uses the constructor of the ancestor.

However, the behavior I would expect (and prefer) is that the resolving fails if it cannot find a correct constructor for the interface you try to resolve.

Example:

TMyClass = class(TInterfacedObject, IMyClass)
  constructor Create(ARequester: IRequester);
end;

TMyDescendant = class(TMyClass, IMyDescendant)
  constructor Create(ARequester: IRequester; AnotherRequester: IOtherRequester);
end;

GlobalContainer.Resolve<IMyDescendant>

In this example it will call the constructor of TMyClass if there is no class registered that implements IOtherRequester. This means that any Guard.IsNotNull that are in the constructor of TMyDescendant doesn't work, because that constructor is never called.

Are there ways to resolve this? Of course we could override the constructor of TMyClass in TMyDescendant, but I prefer a more clean way to do this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笨死的猪 2025-01-20 01:29:05

这个问题有多种解决方案。

  1. Spring.Container.ActivatorExtension 单元中有一个容器扩展。
    您只需像这样注册它:

    GlobalContainer.AddExtension;
    

    这会将整个容器的构造函数发现行为更改为仅考虑具有任何构造函数的最派生类的构造函数,从而避免返回到TObject.Create 如果缺少任何依赖项。

    请记住,即使您可以在两个参数构造函数上编写重载并且没有注册IOtherRequester,它也不会转到它可以的TMyClass构造函数鉴于您注册了一些 IRequester,因此满足。这是因为 RTTI 不包含任何有关重载的信息,即使它包含,也意味着容器必须实现重载解析,这可能会变得非常复杂。

  2. [Inject]注释你的构造函数(记住将单元Spring.Container.Common添加到使用中,否则它不会有任何效果 - 取决于编译器版本您将看到 W1074 警告)

    这将强制容器仅考虑此构造函数并忽略任何其他构造函数。事实上,您可以用它注释两个构造函数 - 它总是会首先找到最派生的构造函数。如果您从 TMyClass 继承其他没有引入自己的构造函数的类,那么它将强制使用 TMyClass 中的类。

There are multiple solutions to this problem.

  1. There is a container extension for that in the unit Spring.Container.ActivatorExtension.
    You simple have to register it like so:

    GlobalContainer.AddExtension<TActivatorContainerExtension>;
    

    This changes the behavior of the constructor discovery for the entire container to only consider the constructors of the most derived class that has any constructors and thus avoids going back to TObject.Create if any dependencies are missing.

    Keep in mind that even though you could have written overload on your two param constructor and not having registered IOtherRequesterit would thus not go to the TMyClass constructor which it could satisfy given that you registered some IRequester. This is because RTTI does not include any information about overloads and even if it would that would mean the container then would have to implement overload resolution which can get quite complicated.

  2. Annotate your constructor with [Inject] (remember to add the unit Spring.Container.Common to the uses or it will not have any effect - depending on the compiler version you then will see the W1074 warning)

    This will force to container to only consider this ctor and ignore any other. You can in fact annotate both constructors with it - it will always find the most derived one first. If you would inherit other classes from TMyClass that don't introduce their own constructors it will then force the one from TMyClass to be used.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文