From 75ea342808ca8cb8b6d77be81b65e594a4723c9c Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 30 May 2023 19:03:53 -0500 Subject: [PATCH 1/2] Add IHostApplicationBuilder and implement it in HostApplicationBuilder. - Move ILoggingBuilder from MS.Ext.Logging to MS.Ext.Logging.Abstractions so IHostApplicationBuilder can reference it. - Add IConfigurationManager and implement it in ConfigurationManager. - Add CompatiibilitySuppressions. These errors are caused by ILoggingBuilder being moved to Logging.Abstractions, and ApiCompat not respecting TypeForwardedTo attributes. Fix #85486 --- ...t.Extensions.Configuration.Abstractions.cs | 25 ++++--- .../src/IConfigurationManager.cs | 15 ++++ .../ref/Microsoft.Extensions.Configuration.cs | 2 +- .../src/ConfigurationManager.cs | 9 ++- ...crosoft.Extensions.Hosting.Abstractions.cs | 9 +++ .../src/IHostApplicationBuilder.cs | 65 +++++++++++++++++ ...oft.Extensions.Hosting.Abstractions.csproj | 1 + .../ref/Microsoft.Extensions.Hosting.cs | 4 +- .../src/HostApplicationBuilder.cs | 45 ++++-------- .../UnitTests/IHostApplicationBuilderTests.cs | 69 +++++++++++++++++++ ...crosoft.Extensions.Logging.Abstractions.cs | 4 ++ ...oft.Extensions.Logging.Abstractions.csproj | 4 ++ .../src/ILoggingBuilder.cs | 0 ...oft.Extensions.Logging.Abstractions.csproj | 2 + .../Microsoft.Extensions.Logging.Forwards.cs | 7 ++ .../ref/Microsoft.Extensions.Logging.cs | 4 -- .../ref/Microsoft.Extensions.Logging.csproj | 1 + .../src/Properties/TypeForwards.cs | 4 ++ .../Common/LoggerBuilderExtensionsTests.cs | 12 ++++ 19 files changed, 232 insertions(+), 50 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/IConfigurationManager.cs create mode 100644 src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/IHostApplicationBuilder.cs create mode 100644 src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/IHostApplicationBuilderTests.cs rename src/libraries/{Microsoft.Extensions.Logging => Microsoft.Extensions.Logging.Abstractions}/src/ILoggingBuilder.cs (100%) create mode 100644 src/libraries/Microsoft.Extensions.Logging/ref/Microsoft.Extensions.Logging.Forwards.cs create mode 100644 src/libraries/Microsoft.Extensions.Logging/src/Properties/TypeForwards.cs diff --git a/src/libraries/Microsoft.Extensions.Configuration.Abstractions/ref/Microsoft.Extensions.Configuration.Abstractions.cs b/src/libraries/Microsoft.Extensions.Configuration.Abstractions/ref/Microsoft.Extensions.Configuration.Abstractions.cs index 9123a251623506..03f00e5749e9b9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Abstractions/ref/Microsoft.Extensions.Configuration.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Abstractions/ref/Microsoft.Extensions.Configuration.Abstractions.cs @@ -6,12 +6,22 @@ namespace Microsoft.Extensions.Configuration { + public readonly partial struct ConfigurationDebugViewContext + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public ConfigurationDebugViewContext(string path, string key, string? value, Microsoft.Extensions.Configuration.IConfigurationProvider configurationProvider) { throw null; } + public Microsoft.Extensions.Configuration.IConfigurationProvider ConfigurationProvider { get { throw null; } } + public string Key { get { throw null; } } + public string Path { get { throw null; } } + public string? Value { get { throw null; } } + } public static partial class ConfigurationExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder Add(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action? configureSource) where TSource : Microsoft.Extensions.Configuration.IConfigurationSource, new() { throw null; } public static System.Collections.Generic.IEnumerable> AsEnumerable(this Microsoft.Extensions.Configuration.IConfiguration configuration) { throw null; } public static System.Collections.Generic.IEnumerable> AsEnumerable(this Microsoft.Extensions.Configuration.IConfiguration configuration, bool makePathsRelative) { throw null; } - public static bool Exists([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] this Microsoft.Extensions.Configuration.IConfigurationSection? section) { throw null; } + public static bool Exists([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] this Microsoft.Extensions.Configuration.IConfigurationSection? section) { throw null; } public static string? GetConnectionString(this Microsoft.Extensions.Configuration.IConfiguration configuration, string name) { throw null; } public static Microsoft.Extensions.Configuration.IConfigurationSection GetRequiredSection(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key) { throw null; } } @@ -33,15 +43,7 @@ public static partial class ConfigurationPath public static partial class ConfigurationRootExtensions { public static string GetDebugView(this Microsoft.Extensions.Configuration.IConfigurationRoot root) { throw null; } - public static string GetDebugView(this IConfigurationRoot root, System.Func? processValue) { throw null; } - } - public readonly partial struct ConfigurationDebugViewContext - { - public ConfigurationDebugViewContext(string path, string key, string? value, IConfigurationProvider configurationProvider) { throw null; } - public string Path { get; } - public string Key { get; } - public string? Value { get; } - public IConfigurationProvider ConfigurationProvider { get; } + public static string GetDebugView(this Microsoft.Extensions.Configuration.IConfigurationRoot root, System.Func? processValue) { throw null; } } public partial interface IConfiguration { @@ -57,6 +59,9 @@ public partial interface IConfigurationBuilder Microsoft.Extensions.Configuration.IConfigurationBuilder Add(Microsoft.Extensions.Configuration.IConfigurationSource source); Microsoft.Extensions.Configuration.IConfigurationRoot Build(); } + public partial interface IConfigurationManager : Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationBuilder + { + } public partial interface IConfigurationProvider { System.Collections.Generic.IEnumerable GetChildKeys(System.Collections.Generic.IEnumerable earlierKeys, string? parentPath); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/IConfigurationManager.cs b/src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/IConfigurationManager.cs new file mode 100644 index 00000000000000..84293d45035d5a --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/IConfigurationManager.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Extensions.Configuration; + +/// +/// Represents a mutable configuration object. +/// +/// +/// It is both an and an . +/// As sources are added, it updates its current view of configuration. +/// +public interface IConfigurationManager : IConfiguration, IConfigurationBuilder +{ +} diff --git a/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs b/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs index b5c18ee34b897c..63ba6092812d97 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs @@ -44,7 +44,7 @@ public ConfigurationKeyComparer() { } public static Microsoft.Extensions.Configuration.ConfigurationKeyComparer Instance { get { throw null; } } public int Compare(string? x, string? y) { throw null; } } - public sealed partial class ConfigurationManager : Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationBuilder, Microsoft.Extensions.Configuration.IConfigurationRoot, System.IDisposable + public sealed partial class ConfigurationManager : Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationBuilder, Microsoft.Extensions.Configuration.IConfigurationManager, Microsoft.Extensions.Configuration.IConfigurationRoot, System.IDisposable { public ConfigurationManager() { } public string? this[string key] { get { throw null; } set { } } diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs index 9bc08c612dacaf..250f14bb961c30 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs @@ -14,12 +14,15 @@ namespace Microsoft.Extensions.Configuration { /// - /// ConfigurationManager is a mutable configuration object. It is both an and an . - /// As sources are added, it updates its current view of configuration. + /// Represents a mutable configuration object. /// + /// + /// It is both an and an . + /// As sources are added, it updates its current view of configuration. + /// [DebuggerDisplay("{DebuggerToString(),nq}")] [DebuggerTypeProxy(typeof(ConfigurationManagerDebugView))] - public sealed class ConfigurationManager : IConfigurationBuilder, IConfigurationRoot, IDisposable + public sealed class ConfigurationManager : IConfigurationManager, IConfigurationBuilder, IConfigurationRoot, IDisposable { // Concurrently modifying config sources or properties is not thread-safe. However, it is thread-safe to read config while modifying sources or properties. private readonly ConfigurationSources _sources; diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/ref/Microsoft.Extensions.Hosting.Abstractions.cs b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/ref/Microsoft.Extensions.Hosting.Abstractions.cs index b4d493695f125e..88f37fc9546228 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/ref/Microsoft.Extensions.Hosting.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/ref/Microsoft.Extensions.Hosting.Abstractions.cs @@ -97,6 +97,15 @@ public partial interface IHost : System.IDisposable System.Threading.Tasks.Task StartAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } + public partial interface IHostApplicationBuilder + { + Microsoft.Extensions.Configuration.IConfigurationManager Configuration { get; } + Microsoft.Extensions.Hosting.IHostEnvironment Environment { get; } + Microsoft.Extensions.Logging.ILoggingBuilder Logging { get; } + System.Collections.Generic.IDictionary Properties { get; } + Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } + void ConfigureContainer(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory factory, System.Action? configure = null) where TContainerBuilder : notnull; + } public partial interface IHostApplicationLifetime { System.Threading.CancellationToken ApplicationStarted { get; } diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/IHostApplicationBuilder.cs b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/IHostApplicationBuilder.cs new file mode 100644 index 00000000000000..5ae02d03a7b59d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/IHostApplicationBuilder.cs @@ -0,0 +1,65 @@ +// 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 Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.Hosting; + +/// +/// Represents a hosted applications and services builder which helps manage configuration, logging, lifetime, and more. +/// +public interface IHostApplicationBuilder +{ + /// + /// Gets a central location for sharing state between components during the host building process. + /// + IDictionary Properties { get; } + + /// + /// Gets the set of key/value configuration properties. + /// + /// + /// This can be mutated by adding more configuration sources, which will update its current view. + /// + IConfigurationManager Configuration { get; } + + /// + /// Gets the information about the hosting environment an application is running in. + /// + IHostEnvironment Environment { get; } + + /// + /// Gets a collection of logging providers for the application to compose. This is useful for adding new logging providers. + /// + ILoggingBuilder Logging { get; } + + /// + /// Gets a collection of services for the application to compose. This is useful for adding user provided or framework provided services. + /// + IServiceCollection Services { get; } + + /// + /// Registers a instance to be used to create the . + /// + /// The factory object that can create the and . + /// + /// A delegate used to configure the . This can be used to configure services using + /// APIS specific to the implementation. + /// + /// The type of builder provided by the . + /// + /// + /// The is created when this builder is built and so the delegate provided + /// by will run after all other services have been registered. + /// + /// + /// Multiple calls to will replace + /// the previously stored and delegate. + /// + /// + void ConfigureContainer(IServiceProviderFactory factory, Action? configure = null) where TContainerBuilder : notnull; +} diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/Microsoft.Extensions.Hosting.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/Microsoft.Extensions.Hosting.Abstractions.csproj index 598d4bd69cbd53..f7881ef99062f4 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/Microsoft.Extensions.Hosting.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/Microsoft.Extensions.Hosting.Abstractions.csproj @@ -22,6 +22,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs b/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs index d8820aa7133668..4e7804b87d1ca8 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs @@ -32,7 +32,7 @@ public static partial class Host public static Microsoft.Extensions.Hosting.IHostBuilder CreateDefaultBuilder(string[]? args) { throw null; } public static Microsoft.Extensions.Hosting.HostApplicationBuilder CreateEmptyApplicationBuilder(Microsoft.Extensions.Hosting.HostApplicationBuilderSettings? settings) { throw null; } } - public sealed partial class HostApplicationBuilder + public sealed partial class HostApplicationBuilder : Microsoft.Extensions.Hosting.IHostApplicationBuilder { public HostApplicationBuilder() { } public HostApplicationBuilder(Microsoft.Extensions.Hosting.HostApplicationBuilderSettings? settings) { } @@ -40,6 +40,8 @@ public HostApplicationBuilder(string[]? args) { } public Microsoft.Extensions.Configuration.ConfigurationManager Configuration { get { throw null; } } public Microsoft.Extensions.Hosting.IHostEnvironment Environment { get { throw null; } } public Microsoft.Extensions.Logging.ILoggingBuilder Logging { get { throw null; } } + Microsoft.Extensions.Configuration.IConfigurationManager Microsoft.Extensions.Hosting.IHostApplicationBuilder.Configuration { get { throw null; } } + System.Collections.Generic.IDictionary Microsoft.Extensions.Hosting.IHostApplicationBuilder.Properties { get { throw null; } } public Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get { throw null; } } public Microsoft.Extensions.Hosting.IHost Build() { throw null; } public void ConfigureContainer(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory factory, System.Action? configure = null) where TContainerBuilder : notnull { } diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs index cd635f90abfbe8..2de31175450a4a 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs @@ -14,9 +14,9 @@ namespace Microsoft.Extensions.Hosting { /// - /// A builder for hosted applications and services which helps manage configuration, logging, lifetime and more. + /// Represents a hosted applications and services builder which helps manage configuration, logging, lifetime, and more. /// - public sealed class HostApplicationBuilder + public sealed class HostApplicationBuilder : IHostApplicationBuilder { private readonly HostBuilderContext _hostBuilderContext; private readonly ServiceCollection _serviceCollection = new(); @@ -182,45 +182,28 @@ private void Initialize(HostApplicationBuilderSettings settings, out HostBuilder logging = new LoggingBuilder(Services); } - /// - /// Provides information about the hosting environment an application is running in. - /// + IDictionary IHostApplicationBuilder.Properties => _hostBuilderContext.Properties; + + /// public IHostEnvironment Environment => _environment; /// - /// A collection of services for the application to compose. This is useful for adding user provided or framework provided services. + /// Gets the set of key/value configuration properties. /// + /// + /// This can be mutated by adding more configuration sources, which will update its current view. + /// public ConfigurationManager Configuration { get; } - /// - /// A collection of services for the application to compose. This is useful for adding user provided or framework provided services. - /// + IConfigurationManager IHostApplicationBuilder.Configuration => Configuration; + + /// public IServiceCollection Services => _serviceCollection; - /// - /// A collection of logging providers for the application to compose. This is useful for adding new logging providers. - /// + /// public ILoggingBuilder Logging => _logging; - /// - /// Registers a instance to be used to create the . - /// - /// The . - /// - /// A delegate used to configure the . This can be used to configure services using - /// APIS specific to the implementation. - /// - /// The type of builder provided by the . - /// - /// - /// is called by - /// and so the delegate provided by will run after all other services have been registered. - /// - /// - /// Multiple calls to will replace - /// the previously stored and delegate. - /// - /// + /// public void ConfigureContainer(IServiceProviderFactory factory, Action? configure = null) where TContainerBuilder : notnull { _createServiceProvider = () => diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/IHostApplicationBuilderTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/IHostApplicationBuilderTests.cs new file mode 100644 index 00000000000000..e7db2eb8d63cc2 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/IHostApplicationBuilderTests.cs @@ -0,0 +1,69 @@ +// 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.Linq; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting.Fakes; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Console; +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests; + +public class IHostApplicationBuilderTests +{ + [Fact] + public void TestIHostApplicationBuilderCanBeUsedInExtensionMethod() + { + HostApplicationBuilder builder = Host.CreateEmptyApplicationBuilder(new HostApplicationBuilderSettings() + { + EnvironmentName = "Development" + }); + + builder.VerifyBuilderWorks(); + + using IHost host = builder.Build(); + + // VerifyBuilderWorks should have configured a FakeServiceProviderFactory with the following State. + FakeServiceCollection fakeServices = host.Services.GetRequiredService(); + Assert.Equal("Hi!", fakeServices.State); + } +} + +internal static class HostBuilderExtensions +{ + public static void VerifyBuilderWorks(this IHostApplicationBuilder builder) + { + var propertyKey = typeof(HostBuilderExtensions); + builder.Properties[propertyKey] = 3; + Assert.Equal(3, builder.Properties[propertyKey]); + + Assert.Equal(1, builder.Configuration.GetChildren().Count()); + Assert.Equal(2, builder.Configuration.Sources.Count); // there's an empty source by default + Assert.Equal("Development", builder.Configuration[HostDefaults.EnvironmentKey]); + + builder.Configuration.AddInMemoryCollection(new Dictionary + { + { "Key1", "value1" } + }); + + Assert.Equal(2, builder.Configuration.GetChildren().Count()); + Assert.Equal(3, builder.Configuration.Sources.Count); + Assert.Equal("value1", builder.Configuration["Key1"]); + Assert.Null(builder.Configuration["Key2"]); + + Assert.True(builder.Environment.IsDevelopment()); + Assert.NotNull(builder.Environment.ContentRootFileProvider); + + Assert.DoesNotContain(builder.Services, sd => sd.ImplementationType == typeof(ConsoleLoggerProvider)); + builder.Logging.AddConsole(); + Assert.Contains(builder.Services, sd => sd.ImplementationType == typeof(ConsoleLoggerProvider)); + + builder.Services.AddSingleton(typeof(IHostApplicationBuilderTests)); + + builder.ConfigureContainer(new FakeServiceProviderFactory(), container => container.State = "Hi!"); + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs index 72e6ae6afce77a..832ec52812649c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs @@ -44,6 +44,10 @@ public partial interface ILoggerProvider : System.IDisposable public partial interface ILogger : Microsoft.Extensions.Logging.ILogger { } + public interface ILoggingBuilder + { + Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } + } public partial interface ISupportExternalScope { void SetScopeProvider(Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider); diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.csproj index 0b3042fa01cbfd..90242dbf8b96f2 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.csproj @@ -6,4 +6,8 @@ + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging/src/ILoggingBuilder.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/ILoggingBuilder.cs similarity index 100% rename from src/libraries/Microsoft.Extensions.Logging/src/ILoggingBuilder.cs rename to src/libraries/Microsoft.Extensions.Logging.Abstractions/src/ILoggingBuilder.cs diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index afd69709ca517e..98722fec22f1b6 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -37,6 +37,8 @@ Microsoft.Extensions.Logging.Abstractions.NullLogger + + (this Microsoft.Extensions.Logging.LoggerFilterOptions builder, string? category, System.Func levelFilter) where T : Microsoft.Extensions.Logging.ILoggerProvider { throw null; } public static Microsoft.Extensions.Logging.LoggerFilterOptions AddFilter(this Microsoft.Extensions.Logging.LoggerFilterOptions builder, string? category, Microsoft.Extensions.Logging.LogLevel level) where T : Microsoft.Extensions.Logging.ILoggerProvider { throw null; } } - public partial interface ILoggingBuilder - { - Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } - } public partial class LoggerFactory : Microsoft.Extensions.Logging.ILoggerFactory, System.IDisposable { public LoggerFactory() { } diff --git a/src/libraries/Microsoft.Extensions.Logging/ref/Microsoft.Extensions.Logging.csproj b/src/libraries/Microsoft.Extensions.Logging/ref/Microsoft.Extensions.Logging.csproj index 9ded83f82f6ee3..a7d3bfaa6d8815 100644 --- a/src/libraries/Microsoft.Extensions.Logging/ref/Microsoft.Extensions.Logging.csproj +++ b/src/libraries/Microsoft.Extensions.Logging/ref/Microsoft.Extensions.Logging.csproj @@ -5,6 +5,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Logging/src/Properties/TypeForwards.cs b/src/libraries/Microsoft.Extensions.Logging/src/Properties/TypeForwards.cs new file mode 100644 index 00000000000000..a075b0e477ccc6 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging/src/Properties/TypeForwards.cs @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.Extensions.Logging.ILoggingBuilder))] diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/Common/LoggerBuilderExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Logging/tests/Common/LoggerBuilderExtensionsTests.cs index dee690e549d961..70983e3288769f 100644 --- a/src/libraries/Microsoft.Extensions.Logging/tests/Common/LoggerBuilderExtensionsTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging/tests/Common/LoggerBuilderExtensionsTests.cs @@ -1,6 +1,7 @@ // 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 Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -41,5 +42,16 @@ public void CaptureScopesDefaultsToTrue() Assert.True(options.Value.CaptureScopes); } + + /// + /// Verifies that the TypeForwardedTo attribute is defined correctly by ensuring we can + /// reference the ILoggingBuilder type through the Microsoft.Extensions.Logging.dll. + /// + [Fact] + public void TypeForwardIsCorrect() + { + Type builderType = Type.GetType("Microsoft.Extensions.Logging.ILoggingBuilder, Microsoft.Extensions.Logging"); + Assert.Equal(typeof(ILoggingBuilder), builderType); + } } } From 216d1693c50f159d78b936c9a8118700571f466f Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 8 Jun 2023 11:06:13 -0500 Subject: [PATCH 2/2] Respond to PR feedback --- .../src/ConfigurationManager.cs | 2 +- .../tests/UnitTests/IHostApplicationBuilderTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs index 250f14bb961c30..19bde1672ceee2 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs @@ -22,7 +22,7 @@ namespace Microsoft.Extensions.Configuration /// [DebuggerDisplay("{DebuggerToString(),nq}")] [DebuggerTypeProxy(typeof(ConfigurationManagerDebugView))] - public sealed class ConfigurationManager : IConfigurationManager, IConfigurationBuilder, IConfigurationRoot, IDisposable + public sealed class ConfigurationManager : IConfigurationManager, IConfigurationRoot, IDisposable { // Concurrently modifying config sources or properties is not thread-safe. However, it is thread-safe to read config while modifying sources or properties. private readonly ConfigurationSources _sources; diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/IHostApplicationBuilderTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/IHostApplicationBuilderTests.cs index e7db2eb8d63cc2..5eeb3eb834ab71 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/IHostApplicationBuilderTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/IHostApplicationBuilderTests.cs @@ -18,7 +18,7 @@ public class IHostApplicationBuilderTests [Fact] public void TestIHostApplicationBuilderCanBeUsedInExtensionMethod() { - HostApplicationBuilder builder = Host.CreateEmptyApplicationBuilder(new HostApplicationBuilderSettings() + HostApplicationBuilder builder = Host.CreateEmptyApplicationBuilder(new HostApplicationBuilderSettings { EnvironmentName = "Development" }); @@ -47,7 +47,7 @@ public static void VerifyBuilderWorks(this IHostApplicationBuilder builder) builder.Configuration.AddInMemoryCollection(new Dictionary { - { "Key1", "value1" } + ["Key1"] = "value1" }); Assert.Equal(2, builder.Configuration.GetChildren().Count());