通过构造函数或类方法级别注入依赖项?

时间:2012-12-05 19:11:50

标签: design-patterns dependency-injection

需要一个设计建议。 请看下面的课程。 类只有一种方法 类具有将userName和passWord作为参数的构造函数。 问题是 - 如果差异是什么 - 如果我从构造函数中删除用户名和密码 - 并将(userName,password)发送到AuthoriseUser方法

所有这些都是在注入依赖性的背景下

 public class UserNameAuthorisationService : IUserNameAuthorisationService
{
    private readonly string _userName;
    private readonly string _password;
    private readonly IUserNameAuthorisationRepository _usernameAuthRepository;

    public UserNameAuthorisationService(string UserName, string Password, IUserNameAuthorisationRepository UsernameAuthRepository)
    {
        _userName = UserName;
        _password = Password;
        _usernameAuthRepository = UsernameAuthRepository;
    }

    public IUser AuthoriseUser()
    {
        throw new NotImplementedException();
    }
}

提前致谢。

3 个答案:

答案 0 :(得分:2)

好的,一般来说,我尝试遵循这种模式: 如果我有机会,我将使用构造函数注入作为外部依赖项

  1. 我会尽可能使用构造函数注入
  2. 我将使用属性注入,以防无法合并构造函数注入,并且我有一个良好的默认
  3. 方法注入在特定情况下具有某些优势,当依赖关系随每个方法调用而变化时(请查看此处 更多详情:http://manning.com/seemann/DIi.NET_sample_ch04.pdf
  4. 在您的情况下,我会执行以下操作:

    1. 将存储库注入保留在构造函数
    2. 将用户名和密码移动到方法上下文,因为DI容器很可能不会提供它们,但它们是特定于上下文的。我不会将这些参数视为依赖项,而是将其视为值对象。
    3. 将构造函数注入到位是一般DI的最佳方法。最大的优势之一是,您可以轻松查看您的班级是否违反SOLID原则,并且您在一个地方看到了多少依赖项

答案 1 :(得分:1)

定义参数构造函数的主要思想是使用 start 参数启动类。 如果您以后不想更改用户/密码,那么最好使用参数构造函数。

另一方面,如果您要更改用户/密码 - 请使用set方法和无参数构造函数。

BTW,创建一个未完全初始化的类,称为两步构造是一种反模式

答案 2 :(得分:1)

在构造函数中传递初始参数对于非可变对象是好的,就好像你不提供setter方法那样,“不可能”(如果不考虑任何反射技巧)来改变它们。

如果您打算不允许通过API更改此值,则这是实现此要求的唯一方法。否则你可以实现setter。即使是实现setter你也可能认为这个对象不存在(没有用户名和密码),在这种情况下,我会保持setter和构造函数的启动。

正如我所看到的,没有密码/用户名/存储库,这个对象没有任何意义,所以我会在构造函数中保持初始化。

如果AuthoriseUser应该作为一个组件,我会将用户名和密码参数移到UserNameAuthorisationService方法,并且例如有一个唯一的应用程序实例(您的DI容器应该管理它)。在这种情况下,我会通过DI将此对象注入客户端对象。

关键是始终将对象保持在一致状态,而不是使用init()和populate()方法。因此,正如@Maxim所指出的那样,总是完全初始化你的对象并使它们始终处于可用状态,如果调用AuthoriseUser()而没有应该预先填充的强制参数,你就不必抛出异常。