C# 如何向静态类注入依赖关系

C# 如何向静态类注入依赖关系,c#,dependency-injection,C#,Dependency Injection,我一直在用DI制作简单的logger类,但我有一些问题 有一个问题。如果我用DI创建一个logger类。每当我使用它时,我都应该这样使用它 var logger = new LogService(new FileLogger()); logger.WriteLine("message"); 我想让它成为静态类,但并没有办法通过构造函数在静态类中注入依赖项 所以,我这样改变它 public static class LogService() { private static readon

我一直在用DI制作简单的logger类,但我有一些问题

有一个问题。如果我用DI创建一个logger类。每当我使用它时,我都应该这样使用它

var logger = new LogService(new FileLogger());
logger.WriteLine("message");
我想让它成为静态类,但并没有办法通过构造函数在静态类中注入依赖项

所以,我这样改变它

public static class LogService()
{
    private static readonly ILoggable _logger;
    static LogService()
    {
         _logger = new FileLogger();
    }
}
我觉得这太奇怪了。这不是DI


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

对静态类使用依赖项注入(DI)是没有意义的。代替DI,只需向静态类添加一个初始化方法并传入依赖项

public static class LogService
{
    private static ILoggable _logger;

    public static ILoggable Logger
    {
        get
        {
             return _logger;
        }
    }

    public static void InitLogger(ILoggable logger)
    {
         _logger = logger;
    }
}
要使用记录器,请确保首先调用
InitLogger()

LogService.InitLogger(new FileLogger());
LogService.Logger.WriteLine("message");

作为一种实践,依赖注入旨在引入抽象(或)来解耦易失性依赖。易失性依赖项是一个类或模块,除其他外,它可以包含不确定性行为,或者通常是一个可以替换或拦截的类或模块

有关易失性依赖项的更详细讨论,请参阅的

由于
文件记录器
写入磁盘,因此它包含不确定性行为。因此,您引入了
ilogable
抽象。这允许使用者与
FileLogger
实现分离

但是,为了能够成功地将使用者与其易失性依赖项解耦,您需要将该依赖项注入使用者。有三种常见模式可供选择:

  • -依赖项静态定义为类实例构造函数的参数列表
  • -依赖项通过可写实例属性注入使用者
  • -依赖项作为方法参数注入消费者
构造函数注入和属性注入都应用于应用程序(也称为)的启动路径中,并要求使用者将依赖项存储在私有字段中,以便以后重用。这要求构造函数和属性是实例成员,即非静态。静态构造函数不能有任何参数和静态属性导致(见第5.3节),和。这妨碍了可测试性和可维护性

另一方面,方法注入应用于组合根之外,它不存储任何提供的依赖项,而只是使用它

因此,方法注入是三种模式中唯一可以应用于实例和静态方法的模式。

在这种情况下,方法的使用者必须提供依赖项。然而,这确实意味着必须通过构造函数、属性或方法注入为使用者本身提供该依赖关系

您的静态
LogService
示例在其构造函数中创建了
FileLogger
,这是紧密耦合代码的一个很好的示例。这被称为控制反常反模式(第5.1节),或通常可被视为一种控制反常反模式。这与DI相反


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

您想要将依赖项注入静态类的事实表明您可能采用了错误的方法。DI系统不仅能够注入构造函数参数,但更重要的是,要使某些对象看起来像是单例对象——这是静态类的最终结果,即使它们实际上不是对象。通过将类设置为静态,您可以说明它的生命周期。将生命周期管理从类中移开,您将坚持单一责任原则。因此,避免使用静态类,特别是当它们保留一些内部状态时。InitLogger方法不需要返回类型吗?这不是一个构造函数。。。我错过了什么吗?@Jazimov你说得对。我缺少返回类型。。。