design-patterns - 将依赖传递给一个本身不使用它但将其传递给一些内部使用的类的类是否正确

标签 design-patterns dependency-injection constructor

正是这个博客让我非常困惑:
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)大量依赖项,但这并不一定意味着类本身做得太多。博客说这太可怕了。给定三个要求,是否有更好或更合适的方法来处理此问题:
  • AccessGateKeeper 必须是内部和密封的。
  • 出于测试原因,类库中没有 IoC。
  • 不想使用属性/方法注入(inject),因为它不太健壮。
  • 最佳答案

    不使用依赖项只是为了传递它的规则是正确的,但从您的公共(public) API 的角度来看,这也不是您正在做的事情。由于AccessGateKeeper是内部的,它不是公共(public) API 的一部分 - 它是 实现细节 .它也可能是 UserAccessManagement 的私有(private)辅助函数。类(class)。

    因此,从公众的角度来看,UserAccessManagement类没有依赖“只是为了传递它”。相反,您可以说 UserAccessManagement类需要依赖 IUserRepository , IHashProviderITokenEncryptor执行其工作。

    然而,从可维护性的角度来看,当前的实现紧密耦合 UserAccessManagementAccessGateKeeper这可能是也可能不是问题。但是,如果这是一个问题,您可以考虑将所需的行为包装在接口(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/

    相关文章:

    python - 使用 Boost Python 公开带有带有数组参数的构造函数的类

    python - python类的奇怪行为

    c# - 如何检查无参数构造函数的类型?

    design-patterns - 长对象调用链有天生的错误吗?

    design-patterns - 在域模型中使用大量服务类是什么的标志

    c# - unity 或 unity.mvc4 用于 MVC4 应用程序

    c# - CaSTLeWindsor LifeStyle.PerWebRequest 表现得像单例

    c# - 如何在没有接口(interface)的情况下模拟多重继承?

    开源项目中的 C++ 类设计模式

    java - @PostConstruct 的执行顺序