在 ASP.NET 中使用依赖注入和工厂模式传递服务

2023-11-22

我正在使用 ASP.NET Core,我知道框架已经提供了这样的日志记录机制,但用这个来说明我的问题。

我正在使用工厂模式来构建 Logger 类,因为我不知道日志记录的类型(因为它存储在数据库中)。

ILogger 合约

Log(string msg)

然后 LoggerFactory 将根据从 DB 传递的参数创建 Logger 后返回一个 ILogger:

public class LoggerFactory
{
    public static Contracts.ILogger BuildLogger(LogType type)
    {
        return GetLogger(type);
    }

//other code is omitted, GetLogger will return an implementation of the related logger

现在,当我需要使用记录器时,我必须这样做:

  public class MyService
{
    private ILogger _logger
    public MyService()
    {
        _logger = LoggerFactory.BuildLogger("myType");
    }

但是,我打算保留我的类而不进行任何实例化,我需要在 MyService 中使用构造函数 DI,并且需要在 Startup 上注入所有依赖项:

    services.AddTransient<Contracts.ILogger, LoggerFactory.BuildLogger("param") > ();

但这是行不通的,我们需要通过一个具体的实现。 如何使用 DI 来实现这一点,有更好的方法来实现吗?


您的方法存在一些错误:

  • 您的服务取决于具体情况LoggerFactory类型是依赖倒置原则违反。
  • 进行这种额外的初始化可能会使构建对象图变得不可靠,而注入构造函数应该很简单.
  • 它掩盖了这样一个事实:ILogger是您的消费者所依赖的真正服务。这使得系统更难测试、更难维护,并且使对象图分析变得复杂。
  • 工厂的使用是一种气味,因为工厂几乎从来都不是正确的解决方案.

相反,您的服务应如下所示:

public class MyService
{
    private ILogger _logger;
    public MyService(ILogger logger)
    {
        _logger = logger;
    }
}

这极大地简化了所有依赖于ILogger。这也意味着获得正确的ILogger for MyService成为的责任成分根,这是拥有这些知识的正确位置。

然而,这确实意味着您可能需要从 ASP.NET Core 的内置 DI 容器迁移到功能更丰富的 DI 库,因为内置容器无法进行上下文感知注册ILogger同时让库自动连接其他构造函数依赖项。

使用 ASP.NET Core DI 容器,您只能使用委托手动连接您的服务。例如:

services.AddTransient<MyService>(c => new MyService(
    BuildLogger(typeof(MyService).Name),
    c.GetRequiredService<ISomeOtherDependency>(),
    c.GetRequiredService<IYetAnotherOne>());
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 ASP.NET 中使用依赖注入和工厂模式传递服务 的相关文章

随机推荐