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

如何在C# .NET中实现方法依赖注入并解决日志参数缺失问题

问题:如何实现日志记录器的方法依赖注入?

我尝试实现一个写入文件的日志记录器,日志文件路径存储在appSettings.json中,已通过模型类关联该配置。以下是我的LogWriter.cs代码:

public class LogWriter
{
    public void WriteLog(string message, IOptions<AppSettings> appSettings)
    {
        AppSettings _appSettings = appSettings.Value;
        using (StreamWriter writer = new StreamWriter(_appSettings.LogFilePath))
        {
            writer.Write("[" + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") +"] " + message);
        }
    }
}

我希望通过WriteLog方法注入appSettings依赖,无需实例化LogWriter类即可调用该方法,以下是program.cs的依赖配置代码:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

var appSettings = new AppSettings();
builder.Configuration.GetSection("AppSettings").Bind(appSettings);

//Add services to the container.
builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("AppSettings"));
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddScoped<IMessageService, MessageService>();
builder.Services.AddScoped<LogWriter>();// DI for LogWriter

builder.Services.AddDbContext<MailContext>(
    o => o.UseNpgsql(appSettings.ConnectionStrings.MailDb)
    );

var app = builder.Build();

app.UseSwagger();
app.UseSwaggerUI();

app.UseAuthorization();
app.MapControllers();

app.Run();

但当我在控制器中以LogWriter.WriteLog("Construktor wird ausgeführt")方式调用时,提示缺少一个参数,控制器代码如下:

[Route("[controller]")]
[ApiController]
public class MessageController : ControllerBase
{
    private readonly IMessageService _mailService;

    public MessageController(IMessageService mailServiceCustom )
    {
        _mailService = mailServiceCustom;
        LogWriter.WriteLog("Construktor wird ausgeführt");

    }
// ...
}

解决方案

方案一:遵循.NET依赖注入最佳实践(推荐)

这种方式通过构造函数注入依赖,符合DI设计原则,便于测试和维护:

  1. 重构LogWriter,将配置依赖移至构造函数
    把IOptions<AppSettings>通过构造函数注入,同时修复日志写入时的覆盖问题(添加append: true参数,并用WriteLine实现换行):

    public class LogWriter
    {
        private readonly AppSettings _appSettings;
    
        // 构造函数注入配置
        public LogWriter(IOptions<AppSettings> appSettings)
        {
            _appSettings = appSettings.Value;
        }
    
        public void WriteLog(string message)
        {
            // 追加写入日志,避免覆盖原有内容
            using (StreamWriter writer = new StreamWriter(_appSettings.LogFilePath, append: true))
            {
                writer.WriteLine($"[{DateTime.Now:MM/dd/yyyy HH:mm:ss}] {message}");
            }
        }
    }
    
  2. 在控制器中注入LogWriter实例
    修改控制器构造函数,注入LogWriter,然后调用实例方法:

    [Route("[controller]")]
    [ApiController]
    public class MessageController : ControllerBase
    {
        private readonly IMessageService _mailService;
        private readonly LogWriter _logWriter;
    
        // 构造函数注入LogWriter
        public MessageController(IMessageService mailServiceCustom, LogWriter logWriter)
        {
            _mailService = mailServiceCustom;
            _logWriter.WriteLog("Construktor wird ausgeführt");
        }
    
        // 其他控制器方法...
    }
    
  3. 保持现有Program.cs配置不变
    你已经添加了builder.Services.AddScoped<LogWriter>();,这部分配置无需修改,DI容器会自动处理依赖注入。


方案二:静态调用方式(不推荐)

如果一定要无需实例化即可调用,可以将LogWriter改为静态类,并在程序启动时初始化配置:

  1. 修改LogWriter为静态类

    public static class LogWriter
    {
        private static AppSettings _appSettings;
    
        // 初始化配置,在程序启动时调用
        public static void Initialize(IOptions<AppSettings> appSettings)
        {
            _appSettings = appSettings.Value;
        }
    
        public static void WriteLog(string message)
        {
            using (StreamWriter writer = new StreamWriter(_appSettings.LogFilePath, append: true))
            {
                writer.WriteLine($"[{DateTime.Now:MM/dd/yyyy HH:mm:ss}] {message}");
            }
        }
    }
    
  2. 在Program.cs中初始化静态类

    var app = builder.Build();
    
    // 获取配置服务并初始化静态LogWriter
    var appSettings = app.Services.GetRequiredService<IOptions<AppSettings>>();
    LogWriter.Initialize(appSettings);
    
    // 后续中间件配置不变
    app.UseSwagger();
    app.UseSwaggerUI();
    // ...
    
  3. 控制器中静态调用
    此时可以直接调用LogWriter.WriteLog("Construktor wird ausgeführt");,无需注入实例。

注意:静态类方式耦合度高,难以进行单元测试,不推荐在生产环境使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 17:55:09