You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#工厂模式下如何为各Parser类注入对应ILogger<T>实例

问题解答

一、从工厂为每个Parser传递对应分类日志至BaseParser

要实现这一点,核心是让工厂通过ILoggerFactory创建对应Parser类型的日志实例,再传递给Parser的构造函数,最终传入BaseParser。具体步骤和代码示例如下:

1. 调整基类与子类的构造函数

让BaseParser接受非泛型ILogger作为依赖,子类明确声明需要对应自身类型的泛型ILogger<T>,并将其传递给父类:

// 抽象基类
public abstract class BaseParser
{
    protected readonly ILogger Logger;

    protected BaseParser(ILogger logger)
    {
        Logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public abstract void Parse();
}

// FileParser子类
public class FileParser : BaseParser
{
    public FileParser(ILogger<FileParser> logger) : base(logger)
    {
    }

    public override void Parse()
    {
        Logger.LogInformation("执行文件解析逻辑");
    }
}

// FileParser的具体实现Parser1
public class Parser1 : FileParser
{
    public Parser1(ILogger<Parser1> logger) : base(logger)
    {
    }

    public override void Parse()
    {
        Logger.LogInformation("执行Parser1的文件解析逻辑");
    }
}

2. 改造工厂类,注入ILoggerFactory

将工厂的依赖从ILogger<Factory>改为ILoggerFactory,这样就能为每个Parser类型创建对应的分类日志实例:

public class ParserFactory
{
    private readonly ILoggerFactory _loggerFactory;

    // 注入ILoggerFactory而非具体的ILogger<Factory>
    public ParserFactory(ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
    }

    // 类型安全的具体Parser创建方法(推荐)
    public Parser1 CreateParser1()
    {
        var logger = _loggerFactory.CreateLogger<Parser1>();
        return new Parser1(logger);
    }

    // 通用创建方法(适合多种Parser类型,需反射)
    public T CreateParser<T>() where T : BaseParser
    {
        var logger = _loggerFactory.CreateLogger<T>();
        return (T)Activator.CreateInstance(typeof(T), logger);
    }
}

通过这种方式,BaseParser中使用的Logger会是对应具体子类的分类日志,日志输出时会自动带上子类的类型名称,便于排查问题。

二、注入ILoggerFactory到Parser中创建日志是否属于不良实践

结论:这属于不推荐的不良实践,原因如下:

  • 违背依赖注入原则:依赖注入要求依赖由外部提供,而非组件自行创建。Parser自行通过ILoggerFactory创建日志,相当于把依赖创建的责任揽到自己身上,破坏了DI的解耦理念。
  • 降低可测试性:如果Parser内部创建日志,测试时需要Mock ILoggerFactory才能替换日志实现,相比直接注入ILogger,测试复杂度更高。
  • 隐藏依赖:Parser的构造函数没有显式声明对日志的依赖,其他开发者阅读代码时无法直观发现该组件需要日志功能。
  • 不符合.NET日志最佳实践:.NET官方推荐直接注入ILogger<T>,框架会自动处理日志分类、上下文传递等细节,手动创建容易遗漏配置或导致日志上下文丢失。

仅在极少数特殊场景下(比如运行时动态生成的Parser类型,无法提前在DI容器中注册),注入ILoggerFactory才是必要的折中方案。

内容的提问来源于stack exchange,提问作者Gicu Mironica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:22:52