gpt4 book ai didi

delphi - 在Spring4D中调用GlobalContainer.Resolve时如何传递字符串值作为参数?

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

使用Spring4D时,如何在调用GlobalContainer时传递字符串值作为参数。解析以便在解析的类构造函数上使用该字符串值?

我想解析映射到 TWorker 的 IWorker 类。 TWorker 类的构造函数依赖于 ITool 以及工作人员名称的字符串。

我猜答案在于 TValue 数组中,它可以作为 GlobalContainer.Resolve 的参数给出,但我不明白如何使用它。

我发现这篇关于使用 TParameterOverride 的文章作为调用 GlobalContainer.Resolve 时的参数,这可能有效,但此功能似乎在 Spring4D 1.1 版本中消失了。

我想在注册类型时避免调用 InjectConstructor。

我需要帮助的部分是

GlobalContainer.Resolve<IWorker>([{what do I put here?}]).Work;

这是我的一个小项目

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils,
Spring.Container;

type
IWorker = interface
['{2BBD7E9C-4806-4F01-9B05-9E9DD928D21D}']
procedure Work;
end;

ITool = interface
['{F962209D-4BC3-41C4-9089-0A874632ED1A}']
procedure Use;
end;

TWorker = class(TInterfacedObject, IWorker)
private
FTool: ITool;
FName: string;
procedure Work;
public
constructor Create(tool: ITool; name: string);
end;

THammer = class(TInterfacedObject, ITool)
private
procedure Use;
end;

{ TWorker }
constructor TWorker.Create(tool: ITool; name: string);
begin
FTool := tool;
FName := name;
end;

procedure TWorker.Work;
begin
Writeln(FName + ' is working');
FTool.Use;
end;


{ THammer }
procedure THammer.Use;
begin
Writeln('Using a hammer');
end;


begin
try
GlobalContainer.RegisterType<ITool, THammer>;
GlobalContainer.RegisterType<IWorker, TWorker>; // TWorker constructor = Create(tool: ITool; name: string);
GlobalContainer.Build;

GlobalContainer.Resolve<IWorker>([{what do I put here?}]).Work;
GlobalContainer.Resolve<IWorker>(['THammer.Create', 'Bob']).Work; //--> 'Unsatisfied constructor on type: TWorker'
GlobalContainer.Resolve<IWorker>([THammer.Create, 'Bob']).Work; //--> Access violation
GlobalContainer.Resolve<IWorker>([nil, 'Bob']).Work; //--> 'Unsatisfied constructor on type: TWorker'
Readln;
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
Readln;
end;
end;
end.

如果有帮助,我们将不胜感激。谢谢!

最佳答案

正如 Sam 所说,您应该避免在整个代码中使用容器作为服务定位器,因为这只是将构造函数调用替换为对容器的调用,这会导致比硬连线的所有代码更糟糕的代码。

虽然可以将参数传递给 Resolve 调用,但它确实应该通过使用工厂来解决。

这将是如何传递名称参数的值(该工具由容器注入(inject),因为它知道这一点( TNamedValueSpring.pas 中声明)。

GlobalContainer.Resolve<IWorker>([TNamedValue.Create('name', 'Bob')]).Work;

但是我们可以将该代码与注册工厂结合起来(不幸的是,因为 RTTI 缺乏有关匿名方法类型的信息,我们必须使用 TFunc<...> )

type
TWorkerFactory = TFunc<string, IWorker>;

...

GlobalContainer.RegisterType<ITool, THammer>;
GlobalContainer.RegisterType<IWorker, TWorker>;
GlobalContainer.RegisterInstance<TWorkerFactory>(
function (name: string): IWorker
begin
Result := GlobalContainer.Resolve<IWorker>([TNamedValue.Create('name', name)]);
end);
GlobalContainer.Build;

GlobalContainer.Resolve<TWorkerFactory>.Invoke('Bob').Work;

因此,这使您可以输入 TWorkerFactory参数位于代码中的某个位置,然后容器可以将其注入(inject)。这样,您就可以使用依赖注入(inject)来解耦代码,但不需要对容器有任何直接依赖(事实上,您仍然可以手动连接所有内容,这是我之前所说的规则)

在 1.2 版本中,容器将支持自动工厂创建,因此您可以编写如下代码:

type
{$M+}
TWorkerFactory = reference to function(const name: string): IWorker;

...

GlobalContainer.RegisterFactory<TWorkerFactory>;

这会自动创建一个代理,将工厂方法的参数进一步传递到容器中。

关于delphi - 在Spring4D中调用GlobalContainer.Resolve时如何传递字符串值作为参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29482322/

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