龙腾猫跃 5 месяцев назад
Родитель
Сommit
ffb79cf1eb
1 измененных файлов с 105 добавлено и 174 удалено
  1. 105 174
      Shared/General/Logger.cs

+ 105 - 174
Shared/General/Logger.cs

@@ -41,38 +41,28 @@ public enum LogBehavior {
 public static class Logger {
     public static BaseLogger Instance { get; set; } = new();
 
-    // 转发给实例的方法包装
-    public static void Log(string message, LogLevel level = LogLevel.Info, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") 
+    // 转发给 BaseLogger 实例的对外方法
+
+    public static void Log(string message, LogLevel level = LogLevel.Info, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "")
         => Instance.Log(message, level, behavior, filePath);
-    public static void Trace(string message, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") 
+    public static void Trace(string message, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "")
         => Log(message, LogLevel.Trace, behavior, filePath);
-    public static void Info(string message, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") 
+    public static void Info(string message, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "")
         => Log(message, LogLevel.Info, behavior, filePath);
-    public static void Warn(string message, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "") 
+    public static void Warn(string message, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "")
         => Log(message, LogLevel.Warn, behavior, filePath);
-    public static void Error(string message, LogBehavior behavior = LogBehavior.AlertThenFeedback, [CallerFilePath] string filePath = "") 
+    public static void Error(string message, LogBehavior behavior = LogBehavior.AlertThenFeedback, [CallerFilePath] string filePath = "")
         => Log(message, LogLevel.Error, behavior, filePath);
 
-    public static void Log(LogLevel level, [InterpolatedStringHandlerArgument("level")] ref LogInterpolatedStringHandler handler, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") {
-        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), level, behavior, filePath); }
-    public static void Trace(ref TraceLogInterpolatedStringHandler handler, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") {
-        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), LogLevel.Trace, behavior, filePath); }
-    public static void Info(ref InfoLogInterpolatedStringHandler handler, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") {
-        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), LogLevel.Info, behavior, filePath); }
-    public static void Warn(ref WarnLogInterpolatedStringHandler handler, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "") {
-        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), LogLevel.Warn, behavior, filePath); }
-    public static void Error(ref ErrorLogInterpolatedStringHandler handler, LogBehavior behavior = LogBehavior.AlertThenFeedback, [CallerFilePath] string filePath = "") {
-        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), LogLevel.Error, behavior, filePath); }
-
-    public static void Log(Exception ex, string? message = null, LogLevel level = LogLevel.Warn, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "") 
+    public static void Log(Exception ex, string? message = null, LogLevel level = LogLevel.Warn, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "")
         => Instance.Log(ex, message, level, behavior, filePath);
-    public static void Trace(Exception ex, string? message = null, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") 
+    public static void Trace(Exception ex, string? message = null, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "")
         => Log(ex, message, LogLevel.Trace, behavior, filePath);
-    public static void Info(Exception ex, string? message = null, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") 
+    public static void Info(Exception ex, string? message = null, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "")
         => Log(ex, message, LogLevel.Info, behavior, filePath);
-    public static void Warn(Exception ex, string? message = null, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "") 
+    public static void Warn(Exception ex, string? message = null, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "")
         => Log(ex, message, LogLevel.Warn, behavior, filePath);
-    public static void Error(Exception ex, string? message = null, LogBehavior behavior = LogBehavior.AlertThenFeedback, [CallerFilePath] string filePath = "") 
+    public static void Error(Exception ex, string? message = null, LogBehavior behavior = LogBehavior.AlertThenFeedback, [CallerFilePath] string filePath = "")
         => Log(ex, message, LogLevel.Error, behavior, filePath);
 
     /// <summary>
@@ -88,6 +78,98 @@ public static class Logger {
     public static void SendToDebug(Exception ex, string? message = null, LogLevel level = LogLevel.Error, [CallerFilePath] string filePath = "")
         => Debug.WriteLine($"{BaseLogger.GetLogPrefix(level, filePath)}{(message is null ? "" : $"{message}:")}{ex.GetDisplay(true)}");
 
+    #region 内插优化
+
+    // VB.NET:由于不兼容 InterpolatedStringHandler,只能手动使用 Lambda
+
+    public static void Log(Func<string?> messageFactory, LogLevel level = LogLevel.Info, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") {
+        if (Instance.MinLevel > level) return;
+        Instance.Log(messageFactory() ?? string.Empty, level, behavior, filePath);
+    }
+    public static void Trace(Func<string?> messageFactory, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "")
+        => Log(messageFactory, LogLevel.Trace, behavior, filePath);
+    public static void Info(Func<string?> messageFactory, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "")
+        => Log(messageFactory, LogLevel.Info, behavior, filePath);
+    public static void Warn(Func<string?> messageFactory, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "")
+        => Log(messageFactory, LogLevel.Warn, behavior, filePath);
+    public static void Error(Func<string?> messageFactory, LogBehavior behavior = LogBehavior.AlertThenFeedback, [CallerFilePath] string filePath = "")
+        => Log(messageFactory, LogLevel.Error, behavior, filePath);
+
+    // C#:仅当实际需要输出日志时,才格式化内插字符串,以优化性能
+
+    public static void Log(LogLevel level, [InterpolatedStringHandlerArgument("level")] ref LogInterpolatedStringHandler handler, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") {
+        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), level, behavior, filePath);
+    }
+    public static void Trace(ref LogInterpolatedStringHandler<TraceLogLevel> handler, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") {
+        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), LogLevel.Trace, behavior, filePath);
+    }
+    public static void Info(ref LogInterpolatedStringHandler<InfoLogLevel> handler, LogBehavior behavior = LogBehavior.None, [CallerFilePath] string filePath = "") {
+        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), LogLevel.Info, behavior, filePath);
+    }
+    public static void Warn(ref LogInterpolatedStringHandler<WarnLogLevel> handler, LogBehavior behavior = LogBehavior.ToastIfDebug, [CallerFilePath] string filePath = "") {
+        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), LogLevel.Warn, behavior, filePath);
+    }
+    public static void Error(ref LogInterpolatedStringHandler<ErrorLogLevel> handler, LogBehavior behavior = LogBehavior.AlertThenFeedback, [CallerFilePath] string filePath = "") {
+        if (handler.IsEnabled) Instance.Log(handler.ToStringAndClear(), LogLevel.Error, behavior, filePath);
+    }
+
+    [InterpolatedStringHandler]
+    public ref struct LogInterpolatedStringHandler {
+        private StringBuilder? _sb;
+        public readonly bool IsEnabled;
+        public LogInterpolatedStringHandler(int literalLength, int formattedCount, LogLevel level, out bool isEnabled) {
+            IsEnabled = isEnabled = Logger.Instance.MinLevel <= level;
+            _sb = IsEnabled ? new StringBuilder(literalLength) : null;
+        }
+        public void AppendLiteral(string value) => _sb?.Append(value);
+        public void AppendFormatted<T>(T value) => _sb?.Append(value?.ToString());
+        public void AppendFormatted<T>(T value, string? format) => _sb?.Append(value is IFormattable formattable ? formattable.ToString(format, null) : value?.ToString());
+        public void AppendFormatted<T>(T value, int alignment) {
+            if (_sb is null) return;
+            var s = value?.ToString() ?? string.Empty;
+            _sb.Append(alignment > 0 ? s.PadLeft(alignment) : alignment < 0 ? s.PadRight(-alignment) : s);
+        }
+        public void AppendFormatted<T>(T value, int alignment, string? format) {
+            if (_sb is null) return;
+            var s = value is IFormattable formattable ? formattable.ToString(format, null) : value?.ToString() ?? string.Empty;
+            _sb.Append(alignment > 0 ? s.PadLeft(alignment) : alignment < 0 ? s.PadRight(-alignment) : s);
+        }
+        public void AppendFormatted(string? value) => _sb?.Append(value);
+        public void AppendFormatted(object? value, int alignment = 0, string? format = null) {
+            if (_sb is null) return;
+            var s = value is IFormattable formattable ? formattable.ToString(format, null) : value?.ToString() ?? string.Empty;
+            _sb.Append(alignment > 0 ? s.PadLeft(alignment) : alignment < 0 ? s.PadRight(-alignment) : s);
+        }
+        internal string ToStringAndClear() {
+            var result = _sb?.ToString() ?? string.Empty;
+            _sb = null;
+            return result;
+        }
+    }
+
+    [InterpolatedStringHandler]
+    public ref struct LogInterpolatedStringHandler<TLevel> where TLevel : struct, ILogLevelProvider {
+        private LogInterpolatedStringHandler _inner;
+        public bool IsEnabled => _inner.IsEnabled;
+        public LogInterpolatedStringHandler(int literalLength, int formattedCount, out bool isEnabled) => _inner = new(literalLength, formattedCount, default(TLevel).Level, out isEnabled);
+        public void AppendLiteral(string value) => _inner.AppendLiteral(value);
+        public void AppendFormatted<T>(T value) => _inner.AppendFormatted(value);
+        public void AppendFormatted<T>(T value, string? format) => _inner.AppendFormatted(value, format);
+        public void AppendFormatted<T>(T value, int alignment) => _inner.AppendFormatted(value, alignment);
+        public void AppendFormatted<T>(T value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format);
+        public void AppendFormatted(string? value) => _inner.AppendFormatted(value);
+        public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format);
+        internal string ToStringAndClear() => _inner.ToStringAndClear();
+    }
+
+    public readonly struct TraceLogLevel : ILogLevelProvider { public LogLevel Level => LogLevel.Trace; }
+    public readonly struct InfoLogLevel : ILogLevelProvider { public LogLevel Level => LogLevel.Info; }
+    public readonly struct WarnLogLevel : ILogLevelProvider { public LogLevel Level => LogLevel.Warn; }
+    public readonly struct ErrorLogLevel : ILogLevelProvider { public LogLevel Level => LogLevel.Error; }
+    public interface ILogLevelProvider { LogLevel Level { get; } }
+
+    #endregion
+
 }
 
 /// <summary>
@@ -138,7 +220,7 @@ public class BaseLogger {
             .Select(t => prefix + t)
             .Join("\r\n");
     }
-    public static string GetLogPrefix(LogLevel level, string filePath) 
+    public static string GetLogPrefix(LogLevel level, string filePath)
         => $"{DateTime.Now:HH':'mm':'ss'.'fff} {level.ToString().First()} {(Thread.CurrentThread.Name is null ? "" : $"<{Thread.CurrentThread.Name}> ")}[{Path.GetFileName(filePath).BeforeFirst(".")}] ";
 
     /// <summary>
@@ -156,157 +238,6 @@ public class BaseLogger {
 
 }
 
-/// <summary>
-/// 用于 <see cref="Logger.Log(LogLevel, ref LogInterpolatedStringHandler, LogBehavior, string)"/> 的内插字符串处理器。
-/// 仅当日志等级满足要求时才格式化字符串,避免不必要的字符串拼接开销。
-/// </summary>
-[InterpolatedStringHandler]
-public ref struct LogInterpolatedStringHandler {
-    private StringBuilder? _sb;
-
-    /// <summary>当前日志等级是否满足输出要求。</summary>
-    public readonly bool IsEnabled;
-
-    public LogInterpolatedStringHandler(int literalLength, int formattedCount, LogLevel level, out bool isEnabled) {
-        IsEnabled = isEnabled = Logger.Instance.MinLevel <= level;
-        _sb = IsEnabled ? new StringBuilder(literalLength) : null;
-    }
-
-    /// <summary>追加字面量字符串片段。</summary>
-    public void AppendLiteral(string value) => _sb?.Append(value);
-    /// <summary>追加格式化值。</summary>
-    public void AppendFormatted<T>(T value) => _sb?.Append(value?.ToString());
-    /// <summary>追加带格式字符串的格式化值。</summary>
-    public void AppendFormatted<T>(T value, string? format)
-        => _sb?.Append(value is IFormattable formattable ? formattable.ToString(format, null) : value?.ToString());
-    /// <summary>追加带对齐宽度的格式化值。</summary>
-    public void AppendFormatted<T>(T value, int alignment) {
-        if (_sb is null) return;
-        var s = value?.ToString() ?? string.Empty;
-        _sb.Append(alignment > 0 ? s.PadLeft(alignment) : alignment < 0 ? s.PadRight(-alignment) : s);
-    }
-    /// <summary>追加带对齐宽度和格式字符串的格式化值。</summary>
-    public void AppendFormatted<T>(T value, int alignment, string? format) {
-        if (_sb is null) return;
-        var s = value is IFormattable formattable ? formattable.ToString(format, null) : value?.ToString() ?? string.Empty;
-        _sb.Append(alignment > 0 ? s.PadLeft(alignment) : alignment < 0 ? s.PadRight(-alignment) : s);
-    }
-    /// <summary>追加字符串值。</summary>
-    public void AppendFormatted(string? value) => _sb?.Append(value);
-    /// <summary>追加带对齐宽度和格式字符串的对象值。</summary>
-    public void AppendFormatted(object? value, int alignment = 0, string? format = null) {
-        if (_sb is null) return;
-        var s = value is IFormattable formattable ? formattable.ToString(format, null) : value?.ToString() ?? string.Empty;
-        _sb.Append(alignment > 0 ? s.PadLeft(alignment) : alignment < 0 ? s.PadRight(-alignment) : s);
-    }
-
-    internal string ToStringAndClear() {
-        var result = _sb?.ToString() ?? string.Empty;
-        _sb = null;
-        return result;
-    }
-}
-
-/// <summary>用于 <see cref="Logger.Trace(ref TraceLogInterpolatedStringHandler, LogBehavior, string)"/> 的内插字符串处理器。</summary>
-[InterpolatedStringHandler]
-public ref struct TraceLogInterpolatedStringHandler {
-    private LogInterpolatedStringHandler _inner;
-    /// <inheritdoc cref="LogInterpolatedStringHandler.IsEnabled"/>
-    public bool IsEnabled => _inner.IsEnabled;
-    public TraceLogInterpolatedStringHandler(int literalLength, int formattedCount, out bool isEnabled)
-        => _inner = new(literalLength, formattedCount, LogLevel.Trace, out isEnabled);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendLiteral"/>
-    public void AppendLiteral(string value) => _inner.AppendLiteral(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T)"/>
-    public void AppendFormatted<T>(T value) => _inner.AppendFormatted(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, string?)"/>
-    public void AppendFormatted<T>(T value, string? format) => _inner.AppendFormatted(value, format);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, int)"/>
-    public void AppendFormatted<T>(T value, int alignment) => _inner.AppendFormatted(value, alignment);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, int, string?)"/>
-    public void AppendFormatted<T>(T value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted(string?)"/>
-    public void AppendFormatted(string? value) => _inner.AppendFormatted(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted(object?, int, string?)"/>
-    public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format);
-    internal string ToStringAndClear() => _inner.ToStringAndClear();
-}
-
-/// <summary>用于 <see cref="Logger.Info(ref InfoLogInterpolatedStringHandler, LogBehavior, string)"/> 的内插字符串处理器。</summary>
-[InterpolatedStringHandler]
-public ref struct InfoLogInterpolatedStringHandler {
-    private LogInterpolatedStringHandler _inner;
-    /// <inheritdoc cref="LogInterpolatedStringHandler.IsEnabled"/>
-    public bool IsEnabled => _inner.IsEnabled;
-    public InfoLogInterpolatedStringHandler(int literalLength, int formattedCount, out bool isEnabled)
-        => _inner = new(literalLength, formattedCount, LogLevel.Info, out isEnabled);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendLiteral"/>
-    public void AppendLiteral(string value) => _inner.AppendLiteral(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T)"/>
-    public void AppendFormatted<T>(T value) => _inner.AppendFormatted(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, string?)"/>
-    public void AppendFormatted<T>(T value, string? format) => _inner.AppendFormatted(value, format);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, int)"/>
-    public void AppendFormatted<T>(T value, int alignment) => _inner.AppendFormatted(value, alignment);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, int, string?)"/>
-    public void AppendFormatted<T>(T value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted(string?)"/>
-    public void AppendFormatted(string? value) => _inner.AppendFormatted(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted(object?, int, string?)"/>
-    public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format);
-    internal string ToStringAndClear() => _inner.ToStringAndClear();
-}
-
-/// <summary>用于 <see cref="Logger.Warn(ref WarnLogInterpolatedStringHandler, LogBehavior, string)"/> 的内插字符串处理器。</summary>
-[InterpolatedStringHandler]
-public ref struct WarnLogInterpolatedStringHandler {
-    private LogInterpolatedStringHandler _inner;
-    /// <inheritdoc cref="LogInterpolatedStringHandler.IsEnabled"/>
-    public bool IsEnabled => _inner.IsEnabled;
-    public WarnLogInterpolatedStringHandler(int literalLength, int formattedCount, out bool isEnabled)
-        => _inner = new(literalLength, formattedCount, LogLevel.Warn, out isEnabled);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendLiteral"/>
-    public void AppendLiteral(string value) => _inner.AppendLiteral(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T)"/>
-    public void AppendFormatted<T>(T value) => _inner.AppendFormatted(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, string?)"/>
-    public void AppendFormatted<T>(T value, string? format) => _inner.AppendFormatted(value, format);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, int)"/>
-    public void AppendFormatted<T>(T value, int alignment) => _inner.AppendFormatted(value, alignment);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, int, string?)"/>
-    public void AppendFormatted<T>(T value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted(string?)"/>
-    public void AppendFormatted(string? value) => _inner.AppendFormatted(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted(object?, int, string?)"/>
-    public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format);
-    internal string ToStringAndClear() => _inner.ToStringAndClear();
-}
-
-/// <summary>用于 <see cref="Logger.Error(ref ErrorLogInterpolatedStringHandler, LogBehavior, string)"/> 的内插字符串处理器。</summary>
-[InterpolatedStringHandler]
-public ref struct ErrorLogInterpolatedStringHandler {
-    private LogInterpolatedStringHandler _inner;
-    /// <inheritdoc cref="LogInterpolatedStringHandler.IsEnabled"/>
-    public bool IsEnabled => _inner.IsEnabled;
-    public ErrorLogInterpolatedStringHandler(int literalLength, int formattedCount, out bool isEnabled)
-        => _inner = new(literalLength, formattedCount, LogLevel.Error, out isEnabled);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendLiteral"/>
-    public void AppendLiteral(string value) => _inner.AppendLiteral(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T)"/>
-    public void AppendFormatted<T>(T value) => _inner.AppendFormatted(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, string?)"/>
-    public void AppendFormatted<T>(T value, string? format) => _inner.AppendFormatted(value, format);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, int)"/>
-    public void AppendFormatted<T>(T value, int alignment) => _inner.AppendFormatted(value, alignment);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted{T}(T, int, string?)"/>
-    public void AppendFormatted<T>(T value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted(string?)"/>
-    public void AppendFormatted(string? value) => _inner.AppendFormatted(value);
-    /// <inheritdoc cref="LogInterpolatedStringHandler.AppendFormatted(object?, int, string?)"/>
-    public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format);
-    internal string ToStringAndClear() => _inner.ToStringAndClear();
-}
-
 /// <summary>
 /// 将日志输出到 <see cref="Debug"/> 并写入指定的文件夹,最多保留 5 个文件。
 /// 不实现 <see cref="LogBehavior"/>。