为了账号安全,请及时绑定邮箱和手机立即绑定

如何将依赖项注入静态类

如何将依赖项注入静态类

C#
沧海一幻觉 2022-01-16 20:00:41
我一直在用 DI 制作简单的记录器类,但我有一些问题和疑问。有一个问题。如果我用 DI 创建一个记录器类。每当我使用它时,我都应该这样使用它。var logger = new LogService(new FileLogger());logger.WriteLine("message");我想把它变成静态类,但是没有办法在静态类中通过构造函数注入依赖。所以,我这样改。public static class LogService(){    private static readonly ILoggable _logger;    static LogService()    {         _logger = new FileLogger();    }}我觉得这太奇怪了。这不是DI..没有一种向静态类注入依赖的好方法吗?
查看完整描述

3 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

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

有关 volatile 依赖项的更详细讨论,请参阅我的书的这本可自由阅读的介绍的第 1.3.2 节。

因为您FileLogger写入磁盘,它包含非确定性行为。出于这个原因,您介绍了ILoggable抽象。这允许消费者与实现分离FileLogger

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

构造函数注入和属性注入都应用应用程序的启动路径(也称为Composition Root)中,并要求使用者将依赖项存储在私有字段中以供以后重用。这要求构造函数和属性是实例成员,即非静态的。静态构造函数不能有任何参数,静态属性会导致Ambient Context 反模式(参见第 5.3 节)和Temporal Coupling。这阻碍了可测试性和可维护性。

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

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

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

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

为了防止 volatile 依赖项的紧密耦合,最好的方法是制作LogService非静态并将其 volatile 依赖项注入其唯一的公共构造函数中。


查看完整回答
反对 回复 2022-01-16
?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

将依赖注入 (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");


查看完整回答
反对 回复 2022-01-16
?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

您可以对需要注入静态类的任何对象使用延迟初始化。

https://docs.microsoft.com/en-us/dotnet/api/system.lazy-1?view=net-5.0

这将允许您传递可以在正在运行的实例和需要使用这些对象的其他类/方法之间共享的静态对象。一个示例是您希望在整个应用程序中共享的 HttpClient。您可以在静态类中延迟初始化 HttpClient 并引用静态类来获取 HttpClient。

这是使用 CosmosDB 客户端的另一个示例: https ://docs.microsoft.com/en-us/azure/azure-functions/manage-connections?tabs=csharp#azure-cosmos-db-clients


查看完整回答
反对 回复 2022-01-16
  • 3 回答
  • 0 关注
  • 683 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信