8

是否可以注册一个带有预期从创建点传递的参数的类?

我知道可以这样做:

GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>.
AsTransient.DelegateTo(
    function: TUserProcessor
    begin
      Result := TUserProcessor.Create(GetCurrentUser);
    end
  );

但是那里的参数被绑定到容器被注册的执行上下文,而不是对象被实例化的地方。

例如,这样的事情可能吗?

GlobalContainer.Resolve<IMathService>([FCurrentUser]);

我知道有些人提倡使用非常简单的构造函数,但有时构造函数参数看起来很明显是要走的路:

  1. 构造的对象需要对象参数才能工作,所以必须满足引用。该参数还使该约束在查看类时更加明显。

  2. 如果您尝试使用对象而不首先进行分配,您可以在方法或属性中分配引用并在所有其他方法中引发和异常。我不喜欢编写这种类型的代码,这只是浪费时间,只是使用构造函数参数并在那里检查。代码越少,IMO 就越好。

  3. 此外,被传递的对象对于使用容器构造新对象的对象(例如 Transaction 对象)是本地的,并且具有某种状态(它不是我可以通过容器获得的新对象)。

4

2 回答 2

7

我在 Unity 中添加了解析器覆盖。

所以你可以写:

program Demo;

{$APPTYPE CONSOLE}

uses
  Classes,
  Spring.Container,
  Spring.Container.Resolvers;

type
  IUserUpgrader = interface
    ['{ADC36759-6E40-417D-B6F7-5DCADF8B9C07}']
  end;

  TUser = class(TObject);

  TUserProcessor = class(TInterfacedObject, IUserUpgrader)
  public
    constructor Create(AUser: TUser);
  end;

constructor TUserProcessor.Create(AUser: TUser);
begin
  Writeln('called constructor with passed user');
end;

begin
  GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>;
  GlobalContainer.Build;

  GlobalContainer.Resolve<IUserUpgrader>(
    TOrderedParametersOverride.Create([TUser.Create]));

  GlobalContainer.Resolve<IUserUpgrader>(
    TParameterOverride.Create('AUser', TUser.Create));

  Readln;
end.

编辑 17.09.2018:

这在不久前发生了变化,Resolve 正在接受参数array of TValue。您可以直接在那里传递值,然后必须与 ctor 中的参数列表完全匹配。对于仅部分填充您可以使用TNamedValueTTypedValue来自 Spring.pas的参数

无论如何,我建议使用您的代码注入和使用的工厂,而不是进入容器(全局或非全局)Resolve 方法。

于 2012-05-23T12:59:18.337 回答
0

您可以查看此线程: https ://forums.embarcadero.com/message.jspa?messageID=440741

我已经在框架中对此进行了实现并在我的代码中使用它。如果你要,我发给你。请记住,当他们在代码库中添加类似的功能时,这不是可能的方式。宝泉有我的密码。

如果您尝试在没有所有需要的参数的情况下进行解析,此实现也会处理,并为您提供显示缺少参数的异常。

你像这样使用它:

ServiceLocator.GetService<ISomeObj>(ServiceParameters['paramname1',value1]['paramname2',value2]..);

值存储为 TValue 并且可以是任何值。

向您的类注册参数是使用如下属性完成的:

private
  [ContainerParameter('paramname1')]
  FYourValue1: ...;
  [ContainerParameter('paramname2')]
  FYourValue2: ..;

你也可以做

[ContainerParameter]
FYourValue1:.. 

但是你的参数有'FYourValue1'作为名称。

于 2012-05-06T12:13:39.847 回答