正是这个博客让我非常困惑:
http://ayende.com/blog/124929/your-ctor-says-that-your-code-is-headache-inducing-explanation
假设我有一个提供访问控制服务的类库。我不想在库本身中使用任何 IoC 容器来使其易于测试(因此所有内容都被注入(inject)并且库本身中没有 container.Resolve)。 (WCF 服务和其他使用该库的网站将使用一些容器在构造函数中注入(inject)依赖项。)
假设我的核心类(class)如下所示:
public class UserAccessManagement
{
private readonly IUserRepository _repo;
private readonly IHashProvider _hash;
private readonly ITokenEncryptor _tokenEnc;
public UserAccessManagement(IUserRepository repo, IHashProvider hash, ITokenEncryptor tokenEnc)
{
_repo = repo; _hash = hash; _tokenEnc = tokenEnc;
}
public void GrantAccess(string username, string resource)
{
User user = repo.FindUser(username);
new AccessGateKeeper(user.SpnTicket, _hash, _tokenEnc)
.GrantAccess(resource);
}
}
如您所见,该类并未真正使用哈希和 tokenEnc,但必须将其传递给构造函数,因为在内部它必须将其传递给门卫。出于安全原因,gate keeper 的具体实现必须是一个内部和密封的类,因此它本身不能注入(inject)到可以解决问题的构造函数中。
因此,您最终会通过构造函数注入(inject)大量依赖项,但这并不一定意味着类本身做得太多。博客说这太可怕了。给定三个要求,是否有更好或更合适的方法来处理此问题:
最佳答案
不使用依赖项只是为了传递它的规则是正确的,但从您的公共(public) API 的角度来看,这也不是您正在做的事情。由于AccessGateKeeper
是内部的,它不是公共(public) API 的一部分 - 它是 实现细节 .它也可能是 UserAccessManagement
的私有(private)辅助函数。类(class)。
因此,从公众的角度来看,UserAccessManagement
类没有依赖“只是为了传递它”。相反,您可以说 UserAccessManagement
类需要依赖 IUserRepository
, IHashProvider
和 ITokenEncryptor
执行其工作。
然而,从可维护性的角度来看,当前的实现紧密耦合 UserAccessManagement
和 AccessGateKeeper
这可能是也可能不是问题。但是,如果这是一个问题,您可以考虑将所需的行为包装在接口(interface)中。机械提取可能如下所示:
public interface IAccess
{
void Grant(object ticket, string resource)
}
使用此接口(interface),您可以更改
UserAccessManagement
的实现到:public class UserAccessManagement
{
private readonly IUserRepository _repo;
private readonly IAccess _access;
public UserAccessManagement(IUserRepository repo, IAccess access)
{
_repo = repo;
_access = access;
}
public void GrantAccess(string username, string resource)
{
User user = repo.FindUser(username);
_access.Grant(user.SpnTicket, resource);
}
}
IAccess
的实现可能看起来像这样:public class Access : IAccess
{
private readonly IHashProvider _hash;
private readonly ITokenEncryptor _tokenEnc;
public Access(IHashProvider _hash, ITokenEncryptor _tokenEnc)
{
_hash = hash;
_tokenEnc = tokenEnc;
}
public void Grant(object ticket, string resource)
{
new AccessGateKeeper(ticket, _hash, _tokenEnc)
.GrantAccess(resource);
}
}
关于design-patterns - 将依赖传递给一个本身不使用它但将其传递给一些内部使用的类的类是否正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8030740/