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
相关产品推荐
相关产品推荐

