diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/ref/Microsoft.Extensions.Caching.Memory.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/ref/Microsoft.Extensions.Caching.Memory.cs index 7a13cdf999acb7..e4f2e66b7006cb 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/ref/Microsoft.Extensions.Caching.Memory.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/ref/Microsoft.Extensions.Caching.Memory.cs @@ -42,6 +42,9 @@ public partial class MemoryCacheOptions : Microsoft.Extensions.Options.IOptions< public MemoryCacheOptions() { } public Microsoft.Extensions.Internal.ISystemClock? Clock { get { throw null; } set { } } public double CompactionPercentage { get { throw null; } set { } } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.Obsolete("This property is retained only for compatibility. Remove use and instead call MemoryCache.Compact as needed.", error: true)] + public bool CompactOnMemoryPressure { get; set; } public System.TimeSpan ExpirationScanFrequency { get { throw null; } set { } } Microsoft.Extensions.Caching.Memory.MemoryCacheOptions Microsoft.Extensions.Options.IOptions.Value { get { throw null; } } public long? SizeLimit { get { throw null; } set { } } diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCacheOptions.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCacheOptions.cs index efb5b197d9378c..15a4eaf220e525 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCacheOptions.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCacheOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.ComponentModel; using Microsoft.Extensions.Internal; using Microsoft.Extensions.Options; @@ -42,6 +43,10 @@ public long? SizeLimit } } + [EditorBrowsableAttribute(EditorBrowsableState.Never)] + [Obsolete("This property is retained only for compatibility. Remove use and instead call MemoryCache.Compact as needed.", error: true)] + public bool CompactOnMemoryPressure { get; set; } + /// /// Gets or sets the amount to compact the cache by when the maximum size is exceeded. /// diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs index 0941865d6e3db9..ebdce4441e2861 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs @@ -9,6 +9,30 @@ namespace Microsoft.Extensions.Logging [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static partial class ConsoleLoggerExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Configuration.IConfiguration configuration) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings settings) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.LogLevel minLevel) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.LogLevel minLevel, bool includeScopes) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, bool includeScopes) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Func filter) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Func filter, bool includeScopes) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action configure) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("Binding TOptions to configuration values may require generating dynamic code at runtime.")] @@ -27,6 +51,16 @@ public static partial class ConsoleLoggerExtensions } namespace Microsoft.Extensions.Logging.Console { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.")] + public partial class ConfigurationConsoleLoggerSettings : Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings + { + public ConfigurationConsoleLoggerSettings(Microsoft.Extensions.Configuration.IConfiguration configuration) { } + public Microsoft.Extensions.Primitives.IChangeToken? ChangeToken { get { throw null; } } + public bool IncludeScopes { get { throw null; } } + public Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings Reload() { throw null; } + public bool TryGetSwitch(string name, out Microsoft.Extensions.Logging.LogLevel level) { throw null; } + } public abstract partial class ConsoleFormatter { protected ConsoleFormatter(string name) { } @@ -86,6 +120,27 @@ public enum ConsoleLoggerQueueFullMode Wait = 0, DropWrite = 1, } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.", error: true)] + public partial class ConsoleLoggerSettings : Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings + { + public ConsoleLoggerSettings() { } + public Microsoft.Extensions.Primitives.IChangeToken? ChangeToken { get { throw null; } set { } } + public bool DisableColors { get { throw null; } set { } } + public bool IncludeScopes { get { throw null; } set { } } + public System.Collections.Generic.IDictionary Switches { get { throw null; } set { } } + public Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings Reload() { throw null; } + public bool TryGetSwitch(string name, out Microsoft.Extensions.Logging.LogLevel level) { throw null; } + } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.", error: true)] + public partial interface IConsoleLoggerSettings + { + Microsoft.Extensions.Primitives.IChangeToken? ChangeToken { get; } + bool IncludeScopes { get; } + Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings Reload(); + bool TryGetSwitch(string name, out Microsoft.Extensions.Logging.LogLevel level); + } public partial class JsonConsoleFormatterOptions : Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions { public JsonConsoleFormatterOptions() { } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj index 532e6fe9f79a48..6ac2f32359d4c9 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj @@ -21,6 +21,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConfigurationConsoleLoggerSettings.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConfigurationConsoleLoggerSettings.cs new file mode 100644 index 00000000000000..9ac19144b737b8 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConfigurationConsoleLoggerSettings.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging.Console +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.")] + public class ConfigurationConsoleLoggerSettings : IConsoleLoggerSettings + { + internal readonly IConfiguration _configuration; + + public ConfigurationConsoleLoggerSettings(IConfiguration configuration) + { + _configuration = configuration; + ChangeToken = configuration.GetReloadToken(); + } + + public IChangeToken? ChangeToken { get; private set; } + + public bool IncludeScopes + { + get + { + bool includeScopes; + var value = _configuration["IncludeScopes"]; + if (string.IsNullOrEmpty(value)) + { + return false; + } + else if (bool.TryParse(value, out includeScopes)) + { + return includeScopes; + } + else + { + var message = $"Configuration value '{value}' for setting '{nameof(IncludeScopes)}' is not supported."; + throw new InvalidOperationException(message); + } + } + } + + public IConsoleLoggerSettings Reload() + { + ChangeToken = null!; + return new ConfigurationConsoleLoggerSettings(_configuration); + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + var switches = _configuration.GetSection("LogLevel"); + if (switches == null) + { + level = LogLevel.None; + return false; + } + + var value = switches[name]; + if (string.IsNullOrEmpty(value)) + { + level = LogLevel.None; + return false; + } + else if (Enum.TryParse(value, true, out level)) + { + return true; + } + else + { + var message = $"Configuration value '{value}' for category '{name}' is not supported."; + throw new InvalidOperationException(message); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.Obsolete.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.Obsolete.cs new file mode 100644 index 00000000000000..3ddc4586e98336 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.Obsolete.cs @@ -0,0 +1,126 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Configuration; +using Microsoft.Extensions.Logging.Console; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging +{ + public static partial class ConsoleLoggerExtensions + { + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, Extensions.Configuration.IConfiguration configuration) + { + var settings = new ConfigurationConsoleLoggerSettings(configuration); + return factory.AddConsole(settings); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, Console.IConsoleLoggerSettings settings) + { + factory.AddProvider(new ConsoleLoggerProvider(ConsoleLoggerSettingsAdapter.GetOptionsMonitor(settings))); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, Logging.LogLevel minLevel, bool includeScopes) + { + factory.AddConsole((n, l) => l >= LogLevel.Information, includeScopes); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, Logging.LogLevel minLevel) + { + factory.AddConsole(minLevel, includeScopes: false); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, bool includeScopes) + { + factory.AddConsole((n, l) => l >= LogLevel.Information, includeScopes); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, System.Func filter, bool includeScopes) + { + factory.AddConsole(new ConsoleLoggerSettings() { IncludeScopes = includeScopes }); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, System.Func filter) + { + factory.AddConsole(filter, includeScopes: false); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory) + { + return factory.AddConsole(includeScopes: false); + } + + [Obsolete] + private sealed class ConsoleLoggerSettingsAdapter : IConfigureOptions, IOptionsChangeTokenSource + { + private IConsoleLoggerSettings _settings; + private ConsoleLoggerSettingsAdapter(IConsoleLoggerSettings settings) + { + _settings = settings; + } + + IChangeToken IOptionsChangeTokenSource.GetChangeToken() => _settings.ChangeToken ?? NullChangeToken.Instance; + + string IOptionsChangeTokenSource.Name => Microsoft.Extensions.Options.Options.DefaultName; + + void IConfigureOptions.Configure(ConsoleLoggerOptions options) + { + options.IncludeScopes = _settings.IncludeScopes; + if (_settings is ConfigurationConsoleLoggerSettings configSettings) + { + options.Configure(configSettings._configuration); + } + else if (_settings is ConsoleLoggerSettings consoleSettings) + { + options.DisableColors = consoleSettings.DisableColors; + } + } + + internal static OptionsMonitor GetOptionsMonitor(IConsoleLoggerSettings settings) + { + ConsoleLoggerSettingsAdapter adapter = new(settings); + OptionsFactory factory = new( new IConfigureOptions[] { adapter }, Array.Empty>()); + IOptionsChangeTokenSource[] sources = new IOptionsChangeTokenSource[] { adapter }; + OptionsCache cache = new(); + + return new OptionsMonitor(factory, sources, cache); + } + } + + private sealed class NullChangeToken : IChangeToken, IDisposable + { + internal static NullChangeToken Instance { get; } = new NullChangeToken(); + private NullChangeToken() { } + public bool HasChanged => false; + public bool ActiveChangeCallbacks => false; + public IDisposable RegisterChangeCallback(Action callback, object? state) => this; + public void Dispose() { } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs index f4ffbe9309f301..9a7d5998afd4cb 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs @@ -15,7 +15,7 @@ namespace Microsoft.Extensions.Logging { [UnsupportedOSPlatform("browser")] - public static class ConsoleLoggerExtensions + public static partial class ConsoleLoggerExtensions { internal const string RequiresDynamicCodeMessage = "Binding TOptions to configuration values may require generating dynamic code at runtime."; internal const string TrimmingRequiresUnreferencedCodeMessage = "TOptions's dependent types may have their members trimmed. Ensure all required members are preserved."; diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs index f1f96fd6611424..97d8538f925ce5 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs @@ -16,7 +16,7 @@ namespace Microsoft.Extensions.Logging.Console /// [UnsupportedOSPlatform("browser")] [ProviderAlias("Console")] - public class ConsoleLoggerProvider : ILoggerProvider, ISupportExternalScope + public partial class ConsoleLoggerProvider : ILoggerProvider, ISupportExternalScope { private readonly IOptionsMonitor _options; private readonly ConcurrentDictionary _loggers; diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerSettings.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerSettings.cs new file mode 100644 index 00000000000000..77bd183cef358a --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerSettings.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging.Console +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.", error: true)] + public class ConsoleLoggerSettings : IConsoleLoggerSettings + { + public IChangeToken? ChangeToken { get; set; } + + public bool IncludeScopes { get; set; } + + public bool DisableColors { get; set; } + + public IDictionary Switches { get; set; } = new Dictionary(); + + public IConsoleLoggerSettings Reload() + { + return this; + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + return Switches.TryGetValue(name, out level); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/IConsoleLoggerSettings.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/IConsoleLoggerSettings.cs new file mode 100644 index 00000000000000..81c2b846c5e3ea --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/IConsoleLoggerSettings.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging.Console +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.", error: true)] + public interface IConsoleLoggerSettings + { + bool IncludeScopes { get; } + + IChangeToken? ChangeToken { get; } + + bool TryGetSwitch(string name, out LogLevel level); + + IConsoleLoggerSettings Reload(); + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Debug/ref/Microsoft.Extensions.Logging.Debug.cs b/src/libraries/Microsoft.Extensions.Logging.Debug/ref/Microsoft.Extensions.Logging.Debug.cs index 4e4fb2d98df06d..6b0feb5254e92e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Debug/ref/Microsoft.Extensions.Logging.Debug.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Debug/ref/Microsoft.Extensions.Logging.Debug.cs @@ -8,6 +8,15 @@ namespace Microsoft.Extensions.Logging { public static partial class DebugLoggerFactoryExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddDebug(this Microsoft.Extensions.Logging.ILoggerFactory factory) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddDebug(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.LogLevel minLevel) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddDebug(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Func filter) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddDebug(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLogger.cs b/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLogger.cs index f84e641ace3ddd..eda4262a465d87 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLogger.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLogger.cs @@ -31,8 +31,7 @@ public IDisposable BeginScope(TState state) where TState : notnull /// public bool IsEnabled(LogLevel logLevel) { - // If the filter is null, everything is enabled - // unless the debugger is not attached + // Everything is enabled unless the debugger is not attached return Debugger.IsAttached && logLevel != LogLevel.None; } diff --git a/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLoggerFactoryExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLoggerFactoryExtensions.cs index bf426222c45943..179c27ed805869 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLoggerFactoryExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLoggerFactoryExtensions.cs @@ -4,6 +4,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging.Debug; +using System; +using System.ComponentModel; namespace Microsoft.Extensions.Logging { @@ -12,6 +14,36 @@ namespace Microsoft.Extensions.Logging /// public static class DebugLoggerFactoryExtensions { + /// + /// Adds a debug logger that is enabled for .Information or higher. + /// + /// The extension method argument. + /// The minimum to be logged. This parameter is no longer honored and will be ignored. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddDebug(this ILoggerFactory factory, LogLevel minLevel) => AddDebug(factory); + + /// + /// Adds a debug logger that is enabled as defined by the filter function. + /// + /// The extension method argument. + /// The function used to filter events based on the log level. This parameter is no longer honored and will be ignored. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddDebug(this ILoggerFactory factory, Func filter) => AddDebug(factory); + + /// + /// Adds a debug logger that is enabled for s of minLevel or higher. + /// + /// The extension method argument. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddDebug(this ILoggerFactory factory) + { + factory.AddProvider(new DebugLoggerProvider()); + return factory; + } + /// /// Adds a debug logger named 'Debug' to the factory. /// diff --git a/src/libraries/Microsoft.Extensions.Logging.EventLog/ref/Microsoft.Extensions.Logging.EventLog.cs b/src/libraries/Microsoft.Extensions.Logging.EventLog/ref/Microsoft.Extensions.Logging.EventLog.cs index 523a34dc137dc5..659188403840d8 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventLog/ref/Microsoft.Extensions.Logging.EventLog.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventLog/ref/Microsoft.Extensions.Logging.EventLog.cs @@ -8,6 +8,15 @@ namespace Microsoft.Extensions.Logging { public static partial class EventLoggerFactoryExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddEventLog(this Microsoft.Extensions.Logging.ILoggerFactory factory) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddEventLog(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.EventLog.EventLogSettings settings) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddEventLog(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.LogLevel minLevel) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventLog(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventLog(this Microsoft.Extensions.Logging.ILoggingBuilder builder, Microsoft.Extensions.Logging.EventLog.EventLogSettings settings) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventLog(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action configure) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.Logging.EventLog/src/EventLoggerFactoryExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.EventLog/src/EventLoggerFactoryExtensions.cs index 8ac843c859af08..1ff31e4e1586ac 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventLog/src/EventLoggerFactoryExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventLog/src/EventLoggerFactoryExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.ComponentModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging.EventLog; @@ -13,6 +14,40 @@ namespace Microsoft.Extensions.Logging /// public static class EventLoggerFactoryExtensions { + /// + /// Adds an event logger. Use to enable logging for specific s. + /// + /// The extension method argument. + /// The . + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddEventLog(this ILoggerFactory factory, EventLog.EventLogSettings settings) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(settings); + + factory.AddProvider(new EventLogLoggerProvider(settings)); + return factory; + } + + /// + /// Adds an event logger that is enabled for s of minLevel or higher. + /// + /// The extension method argument. + /// The minimum to be logged + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddEventLog(this ILoggerFactory factory, LogLevel minLevel) => + AddEventLog(factory, new EventLogSettings() { Filter = (_, logLevel) => logLevel >= minLevel }); + + /// + /// Adds an event logger that is enabled for .Information or higher. + /// + /// The extension method argument. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddEventLog(this ILoggerFactory factory) => AddEventLog(factory, LogLevel.Information); + /// /// Adds an event logger named 'EventLog' to the factory. /// diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/ref/Microsoft.Extensions.Logging.EventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/ref/Microsoft.Extensions.Logging.EventSource.cs index 023c42d936c499..0adcc2b6f34903 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/ref/Microsoft.Extensions.Logging.EventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/ref/Microsoft.Extensions.Logging.EventSource.cs @@ -8,6 +8,9 @@ namespace Microsoft.Extensions.Logging { public static partial class EventSourceLoggerFactoryExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddEventSourceLogger(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddEventSourceLogger(this Microsoft.Extensions.Logging.ILoggerFactory factory) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventSourceLogger(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } } } diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/EventSourceLoggerFactoryExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/EventSourceLoggerFactoryExtensions.cs index 7f247bd6caec92..cd92ca6b2aee40 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/EventSourceLoggerFactoryExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/EventSourceLoggerFactoryExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.ComponentModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging.EventSource; @@ -15,7 +16,23 @@ namespace Microsoft.Extensions.Logging public static class EventSourceLoggerFactoryExtensions { /// - /// Adds an event logger named 'EventSource' to the factory. + /// Adds an logger that writes messages to the instance. + /// + /// The extension method argument. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddEventSourceLogger(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddEventSourceLogger(this ILoggerFactory factory) + { + ThrowHelper.ThrowIfNull(factory); + + factory.AddProvider(new EventSourceLoggerProvider(LoggingEventSource.Instance)); + + return factory; + } + + /// + /// Adds an logger that writes messages to the instance. /// /// The extension method argument. /// The so that additional calls can be chained. diff --git a/src/libraries/Microsoft.Extensions.Logging.TraceSource/ref/Microsoft.Extensions.Logging.TraceSource.cs b/src/libraries/Microsoft.Extensions.Logging.TraceSource/ref/Microsoft.Extensions.Logging.TraceSource.cs index 66396cb62448ae..cb8d69261e334f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.TraceSource/ref/Microsoft.Extensions.Logging.TraceSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.TraceSource/ref/Microsoft.Extensions.Logging.TraceSource.cs @@ -8,6 +8,18 @@ namespace Microsoft.Extensions.Logging { public static partial class TraceSourceFactoryExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddTraceSource(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Diagnostics.SourceSwitch sourceSwitch) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddTraceSource(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Diagnostics.SourceSwitch sourceSwitch, System.Diagnostics.TraceListener listener) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddTraceSource(this Microsoft.Extensions.Logging.ILoggerFactory factory, string switchName) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddTraceSource(this Microsoft.Extensions.Logging.ILoggerFactory factory, string switchName, System.Diagnostics.TraceListener listener) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddTraceSource(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Diagnostics.SourceSwitch sourceSwitch) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddTraceSource(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Diagnostics.SourceSwitch sourceSwitch, System.Diagnostics.TraceListener listener) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddTraceSource(this Microsoft.Extensions.Logging.ILoggingBuilder builder, string switchName) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.Logging.TraceSource/src/TraceSourceFactoryExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.TraceSource/src/TraceSourceFactoryExtensions.cs index e8d2bba55a0b16..863a069d50366c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.TraceSource/src/TraceSourceFactoryExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.TraceSource/src/TraceSourceFactoryExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.ComponentModel; using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.TraceSource; @@ -14,7 +15,83 @@ namespace Microsoft.Extensions.Logging public static class TraceSourceFactoryExtensions { /// - /// Adds a TraceSource logger named 'TraceSource' to the factory. + /// Adds a logger that writes to . + /// + /// The to use. + /// The to use. + /// The to use. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddTraceSource(this ILoggerFactory factory, System.Diagnostics.SourceSwitch sourceSwitch, System.Diagnostics.TraceListener listener) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(sourceSwitch); + ThrowHelper.ThrowIfNull(listener); + + factory.AddProvider(new TraceSourceLoggerProvider(sourceSwitch, listener)); + + return factory; + } + + /// + /// Adds a logger that writes to . + /// + /// The to use. + /// The to use. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddTraceSource(this ILoggerFactory factory, System.Diagnostics.SourceSwitch sourceSwitch) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(sourceSwitch); + + factory.AddProvider(new TraceSourceLoggerProvider(sourceSwitch)); + + return factory; + } + + /// + /// Adds a logger that writes to . + /// + /// The to use. + /// The name of the to use. + /// The to use. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddTraceSource(this ILoggerFactory factory, string switchName, System.Diagnostics.TraceListener listener) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(switchName); + ThrowHelper.ThrowIfNull(listener); + + factory.AddProvider(new TraceSourceLoggerProvider(new SourceSwitch(switchName), listener)); + + return factory; + } + + /// + /// Adds a logger that writes to . + /// + /// The to use. + /// The name of the to use. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddTraceSource(this ILoggerFactory factory, string switchName) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(switchName); + + factory.AddProvider(new TraceSourceLoggerProvider(new SourceSwitch(switchName))); + + return factory; + } + + /// + /// Adds a logger that writes to . /// /// The to use. /// The name of the to use. @@ -30,7 +107,7 @@ public static ILoggingBuilder AddTraceSource( } /// - /// Adds a TraceSource logger named 'TraceSource' to the factory. + /// Adds a logger that writes to . /// /// The to use. /// The name of the to use. @@ -49,7 +126,7 @@ public static ILoggingBuilder AddTraceSource( } /// - /// Adds a TraceSource logger named 'TraceSource' to the factory. + /// Adds a logger that writes to . /// /// The to use. /// The to use. @@ -67,9 +144,9 @@ public static ILoggingBuilder AddTraceSource( } /// - /// Adds a TraceSource logger named 'TraceSource' to the factory. + /// Adds a logger that writes to . /// - /// The to use. + /// The to use. /// The to use. /// The to use. /// The so that additional calls can be chained. diff --git a/src/libraries/Microsoft.Extensions.Primitives/ref/Microsoft.Extensions.Primitives.cs b/src/libraries/Microsoft.Extensions.Primitives/ref/Microsoft.Extensions.Primitives.cs index 5811822286a001..a5f5f188981cd6 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/ref/Microsoft.Extensions.Primitives.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/ref/Microsoft.Extensions.Primitives.cs @@ -36,6 +36,20 @@ public partial interface IChangeToken bool HasChanged { get; } System.IDisposable RegisterChangeCallback(System.Action callback, object? state); } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This type is retained only for compatibility. The recommended alternative is string.Create (int length, TState state, System.Buffers.SpanAction action).", error: true)] + public partial struct InplaceStringBuilder + { + private object _dummy; + private int _dummyPrimitive; + public InplaceStringBuilder(int capacity) { throw null; } + public int Capacity { get { throw null; } set { } } + public void Append(Microsoft.Extensions.Primitives.StringSegment segment) { } + public void Append(char c) { } + public void Append(string? value) { } + public void Append(string? value, int offset, int count) { } + public override string? ToString() { throw null; } + } public readonly partial struct StringSegment : System.IEquatable, System.IEquatable { private readonly object _dummy; diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/InplaceStringBuilder.cs b/src/libraries/Microsoft.Extensions.Primitives/src/InplaceStringBuilder.cs new file mode 100644 index 00000000000000..063de6effb2418 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Primitives/src/InplaceStringBuilder.cs @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Microsoft.Extensions.Primitives +{ + [DebuggerDisplay("Value = {_value}")] + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This type is retained only for compatibility. The recommended alternative is string.Create (int length, TState state, System.Buffers.SpanAction action).", error: true)] + public struct InplaceStringBuilder + { + private int _offset; + private int _capacity; + private string? _value; + + public InplaceStringBuilder(int capacity) : this() + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + _capacity = capacity; + } + + public int Capacity + { + get => _capacity; + set + { + if (value < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value); + } + + // _offset > 0 indicates writing state + if (_offset > 0) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Capacity_CannotChangeAfterWriteStarted); + } + + _capacity = value; + } + } + + public void Append(string? value) + { + if (value == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); + } + + Append(value, 0, value.Length); + } + + public void Append(StringSegment segment) + { + Append(segment.Buffer, segment.Offset, segment.Length); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe void Append(string? value, int offset, int count) + { + EnsureValueIsInitialized(); + + if (value == null + || offset < 0 + || value.Length - offset < count + || Capacity - _offset < count) + { + ThrowValidationError(value, offset, count); + } + + fixed (char* destination = _value) + fixed (char* source = value) + { + Unsafe.CopyBlockUnaligned(destination + _offset, source + offset, (uint)count * 2); + _offset += count; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe void Append(char c) + { + EnsureValueIsInitialized(); + + if (_offset >= Capacity) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Capacity_NotEnough, 1, Capacity - _offset); + } + + fixed (char* destination = _value) + { + destination[_offset++] = c; + } + } + + public override string? ToString() + { + if (Capacity != _offset) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Capacity_NotUsedEntirely, Capacity, _offset); + } + + return _value; + } + + private void EnsureValueIsInitialized() + { + _value ??= new string('\0', _capacity); + } + + private void ThrowValidationError(string? value, int offset, int count) + { + if (value == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); + } + + if (offset < 0 || value.Length - offset < count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset); + } + + if (Capacity - _offset < count) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Capacity_NotEnough, value.Length, Capacity - _offset); + } + } + } +}