使用Microsoft.Extensions.Logging编译时日志代码生成遇错误求助
解决LoggerMessage生成器导致的CS0757和CS0102编译错误
问题场景
我在多项目解决方案中重构日志处理逻辑,实现了基于ILoggerProvider的自定义日志提供程序,并通过[LoggerMessage]特性在不同项目中定义专属的日志扩展方法:
基础日志项目中的扩展类
namespace Logger { public static partial class LogBasicExtensions { [LoggerMessage( EventId = 0, Level = LogLevel.Error, Message = "Log basic exception")] public static partial void LogException(this ILogger logger, Exception exception); } }
其他项目中的扩展类
namespace AnotherProject { public static partial class ClientLogExtension { [LoggerMessage( EventId = 1, Level = LogLevel.Information, Message = "Application Started")] public static partial void ApplicationStarted(this ILogger logger); [LoggerMessage( EventId = 2, Level = LogLevel.Information, Message = "Code {coderead} reception from reader {readernumber}")] public static partial void CodeReception(this ILogger logger, string coderead, uint readernumber); } }
编译时触发以下错误:
- CS0757: 分部方法不能有多个实现声明。
- CS0102: 类型“type name”已包含“identifier”的定义。
以下是Microsoft.Extensions.Logging.Generators生成的冲突代码片段:
partial class ClientLogExtension { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.8.27404")] private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.Exception?> __ApplicationStartedCallback = global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(1, nameof(ApplicationStarted)), "Application Started", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.8.27404")] public static partial void ApplicationStarted(this global::Microsoft.Extensions.Logging.ILogger logger) { if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Information)) { __ApplicationStartedCallback(logger, null); } } [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.8.27404")] private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, global::System.String, global::System.UInt32, global::System.Exception?> __CodeReceptionCallback = global::Microsoft.Extensions.Logging.LoggerMessage.Define<global::System.String, global::System.UInt32>(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(2, nameof(CodeReception)), "Code {coderead} reception from reader {readernumber}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.8.27404")] public static partial void CodeReception(this global::Microsoft.Extensions.Logging.ILogger logger, global::System.String coderead, global::System.UInt32 readernumber) { if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Information)) { __CodeReceptionCallback(logger, coderead, readernumber, null); } } }
已尝试重启IDE、重建项目、删除bin/obj目录、重命名类/方法、新建测试解决方案、清理Temp\VSGeneratedDocuments目录,但问题未解决。
解决方案
1. 确保扩展类的全局唯一性
- 检查所有项目中的日志扩展类,保证命名空间+类名的组合完全唯一,跨项目的同名类会被编译器视为同一类型,导致生成器重复生成实现代码。
- 排查项目引用关系,避免某项目意外引用了包含同名扩展类的其他项目。
2. 限制源代码生成器的作用范围
打开项目的.csproj文件,确保只有定义[LoggerMessage]特性的项目才引用生成器,并添加PrivateAssets="all"避免传递引用:
<ItemGroup> <PackageReference Include="Microsoft.Extensions.Logging.Generators" Version="7.0.8" PrivateAssets="all" /> </ItemGroup>
3. 清理生成器缓存
手动清理.NET源代码生成器的本地缓存:
- Windows系统缓存路径:
%USERPROFILE%\.nuget\packages\microsoft.extensions.logging.generators\7.0.8\analyzers\dotnet\cs - 删除该目录下的所有文件后,重新生成解决方案。
4. 重置Visual Studio环境
- 关闭Visual Studio,删除解决方案根目录下的隐藏
.vs目录。 - 打开工具 > 选项 > 文本编辑器 > C# > 高级,确认“启用源代码生成器”选项已勾选。
5. 检查分部类的使用规范
- 确保所有标记
[LoggerMessage]的扩展类仅在同一项目内使用partial修饰符拆分定义,跨项目的分部类会触发生成器冲突。
6. 更新生成器版本
将Microsoft.Extensions.Logging.Generators升级到最新稳定版本,旧版本可能存在类型识别的bug。
内容的提问来源于stack exchange,提问作者Chaos
相关产品推荐
相关产品推荐

