我有下面的例子。
是否有更简单的方法来传递已经为Container注册的接口变量来解决它?
或者,还有其他方法来使用这个特性吗?
,那是我的接口,
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'])
)
]);发布于 2016-06-28 09:10:29
首先,这闻起来像服务定位器反模式 --你应该使用工厂。
当前构造需要有关对象图的知识,并将两个不同的值传递给相同的类型。一家工厂很适合做的事。
因此,您可以为您的情况注册一个工厂,而不是仅仅用使用者代码中的一个解析调用替换一个ctor调用(您应该尽可能避免这样的事情):
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调用的类中。这也有助于提升到复合根。
发布于 2016-06-28 14:38:13
我找到了一个让电话更容易处理的方法。
也许我做得不对。但这会让电话变得更简单。
我创建了一个助手类
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'])
]);https://stackoverflow.com/questions/38063018
复制相似问题