From 19dbb7fb8066ab75a5be7f694f9fffb9510aab30 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 8 Jun 2023 14:25:49 -0500 Subject: [PATCH] Add IHostApplicationBuilder interface (#86974) * 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 --- ...rosoft.Extensions.Configuration.Abstractions.cs | 25 ++++---- .../src/IConfigurationManager.cs | 15 +++++ .../ref/Microsoft.Extensions.Configuration.cs | 2 +- .../src/ConfigurationManager.cs | 9 ++- .../Microsoft.Extensions.Hosting.Abstractions.cs | 9 +++ .../src/IHostApplicationBuilder.cs | 65 ++++++++++++++++++++ ...icrosoft.Extensions.Hosting.Abstractions.csproj | 1 + .../ref/Microsoft.Extensions.Hosting.cs | 4 +- .../src/HostApplicationBuilder.cs | 45 +++++--------- .../UnitTests/IHostApplicationBuilderTests.cs | 69 ++++++++++++++++++++++ .../Microsoft.Extensions.Logging.Abstractions.cs | 4 ++ ...icrosoft.Extensions.Logging.Abstractions.csproj | 4 ++ .../src/ILoggingBuilder.cs | 0 ...icrosoft.Extensions.Logging.Abstractions.csproj | 2 + .../ref/Microsoft.Extensions.Logging.Forwards.cs | 7 +++ .../ref/Microsoft.Extensions.Logging.cs | 4 -- .../ref/Microsoft.Extensions.Logging.csproj | 1 + .../src/Properties/TypeForwards.cs | 4 ++ .../tests/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 9123a25..03f00e5 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 @@ namespace Microsoft.Extensions.Configuration 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 @@ namespace Microsoft.Extensions.Configuration 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 0000000..84293d4 --- /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 b5c18ee..63ba609 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 @@ namespace Microsoft.Extensions.Configuration 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 9bc08c6..19bde16 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs @@ -14,12 +14,15 @@ using Microsoft.Extensions.Primitives; 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, 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 b4d4936..88f37fc 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 @@ namespace Microsoft.Extensions.Hosting 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 0000000..5ae02d0 --- /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 598d4bd..f7881ef 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 d8820aa..4e7804b 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 @@ namespace Microsoft.Extensions.Hosting 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 @@ namespace Microsoft.Extensions.Hosting 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 cd635f9..2de3117 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs @@ -14,9 +14,9 @@ using Microsoft.Extensions.Logging; 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 @@ namespace Microsoft.Extensions.Hosting 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 0000000..5eeb3eb --- /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 72e6ae6..832ec52 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 @@ namespace Microsoft.Extensions.Logging 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 0b3042f..90242db 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 afd6970..98722fe 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 9ded83f..a7d3bfa 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 0000000..a075b0e --- /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 dee690e..70983e3 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 @@ namespace Microsoft.Extensions.Logging.Test 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); + } } } -- 2.7.4