gpt4 book ai didi

delphi - 如何正确地将属性注入(inject)到表单中?

转载 作者:行者123 更新时间:2023-12-03 15:25:15 48 4
gpt4 key购买 nike

我会第二次提出这个问题。请不要怪我。

情况:

我有一个表格

TfrmMain = class(TForm)
private
[Inject('IniFileSettings')]
FSettings: ISettings;
public
end;

我有容器初始化过程:

procedure BuildContainer(const container: TContainer);
begin
container.RegisterType<TIniSettings>.Implements<ISettings>('IniFileSettings');

container.RegisterType<TfrmMain, TfrmMain>.DelegateTo(
function: TfrmMain
begin
Application.CreateForm(TfrmMain, Result);
end);

container.Build;
end;

因此,我通过容器初始化 TfrmMain 和 TIniSettings。

在 .DPR 中我有:

begin
BuildContainer(GlobalContainer);
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
end.

我还有一个 TApplication 助手:

procedure TApplicationHelper.CreateForm(InstanceClass: TComponentClass; var Reference);
var
locator: IServiceLocator;
begin
locator := TServiceLocatorAdapter.Create(GlobalContainer);
if locator.HasService(InstanceClass.ClassInfo) then
TObject(Reference) := GlobalContainer.Resolve(InstanceClass.ClassInfo).AsObject
else
inherited CreateForm(InstanceClass, Reference);
end;

问题:当我尝试时

procedure TfrmMain.FormCreate(Sender: TObject);
begin
s := FSettings.ReadString('Connection', 'Server', 'localhost');
end;

我收到 AV 异常,因为 FSettings 当前为 NIL。

从容器获取 FSettings 对象的正确方法是什么?

更新:

FSettings := GlobalContainer.Resolve<ISettings>;

这一行工作完美...就像上次一样,我在使用 [Inject] 属性时遇到问题。即使使用 Stefan 的解决方案,我也可以使该方法发挥作用:

How to initialize main application form in Spring4D GlobalContainer?

最佳答案

首先,容器不再具有 HasService 的原因是因为该方法已被删除。您可以通过以下方式访问它:

if container.Kernel.Registry.HasService(...) then  // yeah yeah, I know LoD is crying right now ;)

我会避免混合使用 ServiceLocator 和 GlobalContainer。虽然它们应该指向同一个实例,但情况可能并非如此,因为实际上有人可以将其中一个实例指向另一个实例。如果您确实想在这种情况下使用 ServiceLocator,那么也可以从 ServiceLocator 进行解析。但请记住,容器不知道其中的任何内容(即使您必须调用内核的某些不同部分。

但这不是您在设置注入(inject)时面临的问题。你遇到的问题是时机。 FormCreate 方法(我只是猜测它附加到 OnCreate 事件)。因此容器实例化 TfrmMain,事件被调用,然后返回到容器代码,容器代码随后执行所有注入(inject)。因此,在构造期间调用的某些代码中调用尚未通过构造函数注入(inject)的内容是一种时间耦合。

解决这个问题有不同的方法:

  • 将对 FSettings 的访问权限移至稍后触发的某个事件(例如 OnShow 或 OnActivate)
  • 不要使用字段注入(inject),这可能很好,但是会将您的代码耦合到容器,因为“传统”代码无法做到这一点。使用属性注入(inject)和执行代码的 setter。

当您考虑构造函数注入(inject)作为强制依赖项和属性注入(inject)作为可选依赖项时,我会说选择构造函数注入(inject)。但是知道您使用 TComponent 后代,在这种情况下我可能会使用属性注入(inject),尽管该依赖项不是可选的。

关于delphi - 如何正确地将属性注入(inject)到表单中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26531968/

48 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com