如何将依赖项注入静态类 [英] How to inject dependency to static class

查看:122
本文介绍了如何将依赖项注入静态类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在用DI制作简单的记录器类,但是我有一些问题。

I've been making simple logger class with DI but I have some problem and question.

有问题。如果我用DI做一个记录器类。

There is a problem. If I make a logger class with DI. I should use it like this whenever I use it.

var logger = new LogService(new FileLogger());
logger.WriteLine("message");

我想使其成为静态类,但无法通过构造函数在静态中注入依赖项

I want to make it to static class, but there is no way to inject dependency by constructor in static class.

所以,我这样更改。

public static class LogService()
{
    private static readonly ILoggable _logger;
    static LogService()
    {
         _logger = new FileLogger();
    }
}

我认为这太奇怪了。这不是DI。.

I think this is so weird. This is not DI..

是否没有一种将依赖项注入静态类的好方法?

Isn't there a good way to inject dependency to static class?

推荐答案

依赖注入作为一种惯例,旨在引入抽象(或 seams )以解耦易失性依赖项。易失性依赖项是一个类或模块,除其他事项外,它可能包含不确定性行为,或者通常是我们可以替换或拦截的类或模块。有关易失性依赖项的更详细讨论,请参阅第1.3节。 我的书的这本可自由阅读的介绍中的2篇。

Dependency Injection, as a practice, is meant to introduce abstractions (or seams) to decouple volatile dependencies. A volatile dependency is a class or module that, among other things, can contain nondeterministic behavior or in general is something we which to be able to replace or intercept. For a more detailed discussion about volatile dependencies, see section 1.3.2 of this freely readable introduction of my book.

由于您的 FileLogger 写入磁盘,因此它包含不确定行为。因此,您引入了 ILoggable 抽象。这样可以使使用者与 FileLogger 实现分离。

Because your FileLogger writes to disk, it contains nondeterministic behavior. For this reason you introduced the ILoggable abstraction. This allows consumers to be decoupled from the FileLogger implementation.

要想成功地使消费者与其不稳定的依赖关系脱钩,您需要将该依赖注入。共有三种常见模式可供选择:

To be able to successfully decouple a consumer from its volatile dependency, however, you need to inject that dependency into the consumer. There are three common patterns to choose from:


  • 构造函数注入-依赖关系被静态定义为以下参数的列表:类的 instance 构造函数。

  • 属性注入-依赖项通过可写的 instance 属性注入到使用者中

  • 方法注入-依赖项作为方法参数注入到使用者中。

  • Constructor Injection—Dependencies are statically defined as list of parameters to the class's instance constructor.
  • Property Injection—Dependencies are injected into the consumer via writable instance properties.
  • Method Injection—Dependencies are injected into the consumer as method parameters.

构造函数注入和属性注入都在应用程序的启动路径内 进行应用(也称为组合根),并要求使用者将依赖项存储在私有字段中,以备后用。这要求构造函数和属性为实例成员,即非静态的。静态构造函数不能具有任何参数,并且静态属性会导致环境上下文反模式(请参见第5.3章),以及临时耦合。另一方面,这会阻碍可测试性和可维护性。

Both Constructor Injection and Property Injection are applied inside the startup path of the application (a.k.a. the Composition Root) and require the consumer to store the dependency in a private field for later reuse. This requires the constructor and property to be instance members, i.e. non-static. Static constructors can't have any parameters and static properties lead to the Ambient Context anti-pattern (see chapter 5.3), and Temporal Coupling. This hinders testability and maintainability.

方法注入是在成分根的外部内应用的,而 not 存储任何提供的依赖项,而仅使用它。因此,方法注入是可应用于实例方法和静态方法的三种模式中唯一的一种。在这种情况下,方法的 consumer 必须提供依赖项。但是,这确实意味着必须通过构造函数,属性或方法注入为消费者本身提供这种依赖性。

Method injection, on the other hand, is applied outside the Composition Root and it does not store any supplied dependency, but instead merely uses it. Method injection is, therefore, the only of the three patterns that can be applied to both instance and static methods. In that case, the method's consumer must supply the dependency. This does mean, however, that the consumer itself must have been supplied with that dependency either through constructor, property or method injection.

您的静态<$ c $示例在构造函数内部创建 FileLogger 的c> LogService 是紧密耦合代码的一个很好的例子。这被称为控制狂反模式(第5.1章),或者通常可以看作是 DIP违反。这是DI的相反。

Your example of the static LogService that created FileLogger inside its constructor is a great example of tightly coupled code. This is known as the Control Freak anti-pattern (chapter 5.1) or in general can be seen as a DIP violation. This is the opposite of DI.

为防止不稳定依赖关系紧密耦合,最好的方法是使 LogService 非静态,并将其易失性依赖项注入其唯一的公共构造函数中。

To prevent tight coupling of volatile dependencies, the best is to make LogService non-static and inject its volatile dependencies into its sole public constructor.

这篇关于如何将依赖项注入静态类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆