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

C# Maui中MetroLog在服务类中实例为Null的问题求助

解决MetroLog在服务/ViewModel中获取Logger为Null的问题

核心问题原因

你通过LoggerFactory.GetLogger静态方式获取Logger时返回Null,本质是全局LoggerFactory实例未正确初始化,或服务类在LoggerFactory初始化前就被DI容器实例化,导致静态调用无法拿到有效实例。而页面中能正常运行,是因为页面实例化时机晚于LoggerFactory初始化。

正确的依赖注入实现步骤

1. 在MauiProgram.cs中注册MetroLog到DI容器

首先完成MetroLog的配置与DI注册,确保日志工厂和日志器能被容器解析:

var builder = MauiApp.CreateBuilder();

// 1. 配置MetroLog日志工厂,添加输出目标(控制台、文件等)
var loggerFactory = LoggerFactory.Create(logBuilder =>
{
    logBuilder.AddConsoleTarget(); // 控制台输出
    logBuilder.AddFileTarget(options =>
    {
        options.FileNameFormat = "app_log_{yyyyMMdd}.txt";
        options.IncludeLevel = true;
        options.IncludeTimestamp = true;
        options.MaxFileSizeBytes = 1024 * 1024; // 单日志文件最大1MB
    });
});

// 2. 将LoggerFactory和泛型ILogger<T>注册到DI容器
builder.Services.AddSingleton(loggerFactory);
builder.Services.AddScoped(typeof(ILogger<>), typeof(Logger<>));

2. 改造服务类,通过构造函数注入Logger

放弃静态获取方式,直接在服务类的构造函数中注入ILogger<YourServiceType>,同时保留原有依赖(如IdentityService):

public class ArticleService : RestServiceBase
{
    private readonly ILogger<ArticleService> _log;
    private readonly IdentityService _identityService;

    // 构造函数注入所有依赖
    public ArticleService(IdentityService identityService, ILogger<ArticleService> logger)
        : base(/* 若基类需要参数,在此传入,比如logger */)
    {
        _identityService = identityService;
        _log = logger;
    }

    // 业务方法中直接使用日志器
    public async Task<IEnumerable<Article>> FetchArticlesAsync()
    {
        _log.LogInformation("开始获取文章数据");
        try
        {
            // 你的业务逻辑代码
            var articles = await _identityService.HttpClient.GetFromJsonAsync<IEnumerable<Article>>("/api/articles");
            _log.LogInformation("成功获取{Count}篇文章", articles?.Count() ?? 0);
            return articles;
        }
        catch (Exception ex)
        {
            _log.LogError(ex, "获取文章数据失败");
            throw;
        }
    }
}

3. 简化DI服务注册

让DI容器自动解析所有依赖,无需手动new服务实例:

// 先注册IdentityService
builder.Services.AddScoped<IdentityService>();
// 直接注册ArticleService,DI会自动注入所需的IdentityService和ILogger<ArticleService>
builder.Services.AddScoped<ArticleService>();

若基类需要日志的适配

如果RestServiceBase也需要日志能力,可以给基类注入ILogger:

public abstract class RestServiceBase
{
    protected readonly ILogger _baseLogger;

    protected RestServiceBase(ILogger logger)
    {
        _baseLogger = logger;
    }

    // 基类中可封装通用日志方法
    protected void LogRequest(string url)
    {
        _baseLogger.LogInformation("发起请求:{Url}", url);
    }
}

此时ArticleService的构造函数只需将注入的logger传给基类即可:

public ArticleService(IdentityService identityService, ILogger<ArticleService> logger)
    : base(logger)
{
    _identityService = identityService;
    _log = logger;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 02:28:23