依赖注入 - 使用静态依赖项字段而不是注入每个对象

时间:2016-07-13 10:05:23

标签: c# design-patterns dependency-injection

将依赖项对象作为静态类中的静态字段而不是将其注入通过构造函数依赖它的每个对象有什么问题?

public static class Dependencies
{
    public static IUsersRepository Users;
    ...
}
//Use in a method that depends on Users Repository
var users = Dependencies.Users.GetUsers();    

VS

public class UserController
{
    private IUsersRepository _users;
    public UserController(IUsersRepository repo)
    {
        this._users = repo;
    }
    public List<User> GetCustomUsers()
    {
        var users = this._users.GetUsers();
        ...
    }
}

3 个答案:

答案 0 :(得分:3)

您可以使用称为“环境上下文”的DI模式来执行此操作。

它允许您始终避免传递横切关注点,但它仍然允许您进行单元测试。

规范示例是DateTime提供程序:

public abstract class TimeProvider {
   private static TimeProvider current =
   DefaultTimeProvider.Instance;

   public static TimeProvider Current {
      get { return TimeProvider.current; }
      set {
         if (value == null) {
            throw new ArgumentNullException("value");
         }
         TimeProvider.current = value;
      }
   }

   public abstract DateTime UtcNow { get; }

   public static void ResetToDefault() {
      TimeProvider.current = DefaultTimeProvider.Instance;
   }
}

实现可能如下所示:

public class DefaultTimeProvider : TimeProvider {
   private readonly static DefaultTimeProvider instance = 
      new DefaultTimeProvider();

   private DefaultTimeProvider() { }

   public override DateTime UtcNow {
      get { return DateTime.UtcNow; }
   }

   public static DefaultTimeProvider Instance {
      get { return DefaultTimeProvider.instance; }
   }
}    

代码将使用TimeProvider.Current来访问DateTime,而不是直接使用DateTime

默认的具体实现返回通常的DateTime.UtcNow。但是,对于单元测试,您可以使用特殊的测试实现,并在运行单元测试之前将TimeProvider.Current设置为它。

See this page (where that code comes from) for more information.

请注意,您只应将此模式用于真正的跨领域问题,例如DateTime,安全性,日志记录等。

答案 1 :(得分:2)

假设UserController想要使用即时IUsersRepository而另一个UserController想要使用不同IUserRepository实现的实例,那么你就不能使用静态依赖项执行此操作。

答案 2 :(得分:0)

老实说,如果你这样做,警察不会来敲你的门,但是如果得到它的合理结论(即任何可观的大小的应用),你最终会得到更多难以维护&#34;意大利面条代码&#34;代码库。

主要是耦合,以及SOLID principles之类的东西。您正紧密耦合到Dependency类,理想情况下DI通过为您构建对象图来阻止这种情况,注入依赖项,因此这些对象不知道(即没有耦合)提供它们的实现。如果你正在使用DI容器和单身生活方式,那么你基本上得到了你所描述的 - 静态字段。但是对于一个容器(即使是#34;无容器和#34;样式容器越来越受欢迎),您可以获得更大的灵活性,并为您完成艰难的工作。

在某些情况下,使用DI,特别是通过容器,可能是一个坏主意(记录,生成新的Guid值,获取当前日期)。您可以使用&#34;环境上下文&#34;来解决这几个案例。解决方案(有关详细信息,请参阅Matthew Watson's answer)。