From 5046c9752b9651103ee16ae9c7bbef2ae3d7f609 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 18 Apr 2026 21:09:08 +0800 Subject: [PATCH] =?UTF-8?q?fix(review-followup):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E9=85=8D=E7=BD=AE=E7=A9=BA=E9=A1=B9=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E4=B8=8E=E6=96=87=E6=A1=A3=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 ConfigurableLoggerFactory 对 null Appender 配置项的显式校验与 XML 契约 - 补充日志工厂针对 appenders 空项输入的回归测试 - 更新 Godot setting 文档中的 async 示例签名以匹配 ApplyAsync 用法 - 修正 AbstractArchitecture 中 ObserveDestroyCoreAsync 方法里调用await DestroyAsync() 未配置ConfigureAwait(false)的问题 --- .../Logging/ConfigurableLoggerFactoryTests.cs | 18 ++++++++++++++++++ .../Logging/ConfigurableLoggerFactory.cs | 10 +++++++++- .../Architectures/AbstractArchitecture.cs | 4 +--- docs/zh-CN/godot/setting.md | 4 ++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/GFramework.Core.Tests/Logging/ConfigurableLoggerFactoryTests.cs b/GFramework.Core.Tests/Logging/ConfigurableLoggerFactoryTests.cs index 074c9a02..b20dd184 100644 --- a/GFramework.Core.Tests/Logging/ConfigurableLoggerFactoryTests.cs +++ b/GFramework.Core.Tests/Logging/ConfigurableLoggerFactoryTests.cs @@ -36,6 +36,24 @@ public sealed class ConfigurableLoggerFactoryTests }); } + /// + /// 验证当配置输入把 appenders 集合中的某个元素反序列化为 时,工厂会抛出可诊断异常。 + /// + [Test] + public void CreateFactory_ShouldThrowInvalidOperationException_WhenAppenderEntryIsNull() + { + var config = LoggingConfigurationLoader.LoadFromJsonString( + """ + { + "appenders": [ null ] + } + """); + + var exception = Assert.Throws(() => LoggingConfigurationLoader.CreateFactory(config)); + + Assert.That(exception!.Message, Is.EqualTo("Appender configuration cannot be null.")); + } + /// /// 验证在未命中命名空间覆盖时,调用方传入的默认最小级别会作为最终 logger 级别的下限参与计算。 /// diff --git a/GFramework.Core/Logging/ConfigurableLoggerFactory.cs b/GFramework.Core/Logging/ConfigurableLoggerFactory.cs index 5e4b497e..4d1fd064 100644 --- a/GFramework.Core/Logging/ConfigurableLoggerFactory.cs +++ b/GFramework.Core/Logging/ConfigurableLoggerFactory.cs @@ -16,6 +16,8 @@ internal sealed class ConfigurableLoggerFactory : ILoggerFactory, IDisposable /// 初始化一个基于日志配置创建输出管线的工厂实例。 /// /// 日志配置。 + /// + /// 配置中的某个 Appender 项为 public ConfigurableLoggerFactory(LoggingConfiguration config) { _config = config ?? throw new ArgumentNullException(nameof(config)); @@ -23,7 +25,13 @@ internal sealed class ConfigurableLoggerFactory : ILoggerFactory, IDisposable // 反序列化输入可能显式把集合写成 null,这里统一归一化为可安全枚举的空集合。 _config.Appenders ??= []; _config.LoggerLevels ??= new Dictionary(StringComparer.Ordinal); - _appenders = _config.Appenders.Select(LoggingConfigurationLoader.CreateAppender).ToArray(); + + // 外部配置可能把集合项反序列化为 null,这里先给出可诊断异常,避免后续工厂链路出现不清晰的空引用失败。 + _appenders = _config.Appenders + .Select(static appenderConfig => appenderConfig ?? + throw new InvalidOperationException("Appender configuration cannot be null.")) + .Select(LoggingConfigurationLoader.CreateAppender) + .ToArray(); } /// diff --git a/GFramework.Godot/Architectures/AbstractArchitecture.cs b/GFramework.Godot/Architectures/AbstractArchitecture.cs index 668c84ce..1beb8609 100644 --- a/GFramework.Godot/Architectures/AbstractArchitecture.cs +++ b/GFramework.Godot/Architectures/AbstractArchitecture.cs @@ -2,8 +2,6 @@ using GFramework.Core.Abstractions.Environment; using GFramework.Core.Architectures; using GFramework.Core.Constants; -using GFramework.Godot.Extensions; -using Godot; namespace GFramework.Godot.Architectures; @@ -165,7 +163,7 @@ public abstract class AbstractArchitecture( { try { - await DestroyAsync(); + await DestroyAsync().ConfigureAwait(false); } catch (Exception ex) { diff --git a/docs/zh-CN/godot/setting.md b/docs/zh-CN/godot/setting.md index f1c75ae5..8187f303 100644 --- a/docs/zh-CN/godot/setting.md +++ b/docs/zh-CN/godot/setting.md @@ -378,7 +378,7 @@ public class AudioManager : Node ); } - private void SetMasterVolume(float linearVolume) + private async void SetMasterVolume(float linearVolume) { var settings = new AudioSettings { MasterVolume = linearVolume }; var audioSettings = new GodotAudioSettings(settings, new AudioBusMap()); @@ -419,7 +419,7 @@ public class CustomAudioManager : Node ); } - private void SetMasterVolume(float linearVolume) + private async void SetMasterVolume(float linearVolume) { var audioSettingsData = new AudioSettings { MasterVolume = linearVolume }; var audioSettings = new GodotAudioSettings(audioSettingsData, _customBusMap);