如何传递一个接口参数到Spring4D



我有下面的例子:
是否有更简单的方法来传递已经为容器注册的接口变量来解决它?
或者,是否有其他方法使用此功能?


这是我的接口
    IString = interface
      function Value: string;  
    end;  
    IUser = interface
      function Name: IString;
    end;
    ILogin = interface
      function User: IUser;
      function Password: IString;
    end;

类实现

    TString = class(TInterfacedObject, IString)
    private
      FValue: String;
    public
      constructor Create(const AValue: String);
      function Value: String;
    end;
    TUser = class(TInterfacedObject, IUser)
    private
      FName: IString;
    public
      constructor Create(const AName: IString);
      function Name: IString;
    end;
    TLogin = class(TInterfacedObject, ILogin)
    private
      FUser: IUser;
      FPassword: IString;
    public
      constructor Create(const AUser: IUser; const APassword: IString);
      function User: IUser;
      function Password: IString;
    end;

容器

    GlobalContainer.RegisterType<TString>.Implements<IString>;
    GlobalContainer.RegisterType<TUser>.Implements<IUser>;
    GlobalContainer.RegisterType<TLogin>.Implements<ILogin>;

调用
因此,当我必须以这种方式调用创建这些接口时,嵌套的参数使代码变得复杂,并且难以读取(和查看)

    GlobalContainer.Resolve<ILogin>([
      TValue.From(
        GlobalContainer.Resolve<IUser>([
          TValue.From(
            GlobalContainer.Resolve<IString>(['UserName'])
          )
        ])
      ),
      TValue.From(
        GlobalContainer.Resolve<IString>(['SuperSecretPassword'])
      )
    ]);

首先,这有点像服务定位器反模式——你应该使用工厂。

当前构造需要了解对象图并将两个不同的值传递给相同的类型。这是工厂最适合做的事。

因此,与其在消费者代码中用resolve调用替换一个actor调用(这是你应该尽可能避免的),不如为你的案例注册一个factory:

type
  ILoginFactory = interface
    [some guid]
    function CreateLogin(const userName, password: string): ILogin;
  end;
  TLoginFactory = class(TInterfacedObject, ILoginFactory)
    function CreateLogin(const username, password: string): ILogin;
  end;
  function TLoginFactory.CreateLogin(const username, password: string): ILogin;
  begin
    // can also inject the container to the factory and use resolve here - 
    // but doing it the pure DI way for now because the graph to create is simple
    Result := TLogin.Create(
      TUser.Create(
        TString.Create(username)),
      TString.Create(password));
  end;

这个ILoginFactory应该被注入到当前有GlobalContainer.Resolve调用的类中。这也有助于移动到合成根。

我找到了一种使呼叫更容易的方法。
也许我做得不对。但它使调用更简单。

我创建了一个助手类
    TContainerHelper = class helper for TContainer
    public
      ResolveAsTValue<T>: TValue; overload;
      ResolveAsTValue<T>(name: string): TValue; overload;
      ResolveAsTValue<T>(arguments: array of TValue): TValue; overload;
      ResolveAsTValue<T>(name: string;arguments: array of TValue): TValue; overload; 
    end;

现在,当我需要解析一个依赖于另一个接口的接口时,我只需:

    GlobalContainer.Resolve<ILogin>([
      GlobalContainer.ResolveAsTValue<IUser>([
        GlobalContainer.ResolveAsTValue<IString>(['UserName'])
      ]),
      GlobalContainer.ResolveAsTValue<IString>(['SuperSecretPassword'])
    ]);

相关内容

  • 没有找到相关文章

最新更新