我有以下例子 是否有更简单的方法来传递已经为Container注册的Interfaced变量来解决它? 或者,是否有其他方法可以使用此功能?
这是我的界面
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'])
)
]);
答案 0 :(得分:3)
首先,这有点像Service Locator anti pattern - 你应该使用工厂。
当前构造需要有关对象图的知识,并将两个不同的值传递给相同的类型。工厂非常适合的东西。
因此,不仅仅是在消费者代码中使用解决方案调用替换ctor调用(尽可能避免使用),您可以为您的案例注册工厂:
std::istream& operator>>(std::istream &in, someclass &x)
{
in>>x.a;
return in;
}
int main()
{
someclass test;
std::cin>>test;
return 0;
}
然后应将此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
调用的类中。这也有助于提升composition root。
答案 1 :(得分:0)
我找到了一种方法让电话更容易 也许我没有以正确的方式做到这一点。但它使调用更简单。
我创建了一个帮助类
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'])
]);