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 cc1d7d84b9bd1..085bc47a266b0 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/ref/Microsoft.Extensions.Hosting.cs @@ -26,9 +26,11 @@ public ConsoleLifetimeOptions() { } public static partial class Host { public static Microsoft.Extensions.Hosting.HostApplicationBuilder CreateApplicationBuilder() { throw null; } + public static Microsoft.Extensions.Hosting.HostApplicationBuilder CreateApplicationBuilder(Microsoft.Extensions.Hosting.HostApplicationBuilderSettings? settings) { throw null; } public static Microsoft.Extensions.Hosting.HostApplicationBuilder CreateApplicationBuilder(string[]? args) { throw null; } public static Microsoft.Extensions.Hosting.IHostBuilder CreateDefaultBuilder() { throw null; } 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 { diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Host.cs b/src/libraries/Microsoft.Extensions.Hosting/src/Host.cs index a836ec1c2276e..1e21a32117951 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/Host.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/Host.cs @@ -64,15 +64,14 @@ public static IHostBuilder CreateDefaultBuilder(string[]? args) /// /// set the to the result of /// load host from "DOTNET_" prefixed environment variables - /// load host from supplied command line args /// load app from 'appsettings.json' and 'appsettings.[].json' /// load app from User Secrets when is 'Development' using the entry assembly /// load app from environment variables - /// load app from supplied command line args /// configure the to log to the console, debug, and event source output /// enables scope validation on the dependency injection container when is 'Development' /// /// + /// The initialized . public static HostApplicationBuilder CreateApplicationBuilder() => new HostApplicationBuilder(); /// @@ -93,6 +92,20 @@ public static IHostBuilder CreateDefaultBuilder(string[]? args) /// /// /// The command line args. + /// The initialized . public static HostApplicationBuilder CreateApplicationBuilder(string[]? args) => new HostApplicationBuilder(args); + + /// + /// Controls the initial configuration and other settings for constructing the . + public static HostApplicationBuilder CreateApplicationBuilder(HostApplicationBuilderSettings? settings) + => new HostApplicationBuilder(settings); + + /// + /// Initializes a new instance of the class with no pre-configured defaults. + /// + /// Controls the initial configuration and other settings for constructing the . + /// The initialized . + public static HostApplicationBuilder CreateEmptyApplicationBuilder(HostApplicationBuilderSettings? settings) + => new HostApplicationBuilder(settings, empty: true); } } diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs index b3b515ad0bb1f..cd635f90abfbe 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs @@ -20,6 +20,8 @@ public sealed class HostApplicationBuilder { private readonly HostBuilderContext _hostBuilderContext; private readonly ServiceCollection _serviceCollection = new(); + private readonly IHostEnvironment _environment; + private readonly LoggingBuilder _logging; private Func _createServiceProvider; private Action _configureContainer = _ => { }; @@ -89,15 +91,52 @@ public HostApplicationBuilder(HostApplicationBuilderSettings? settings) HostingHostBuilderExtensions.SetDefaultContentRoot(Configuration); } - HostingHostBuilderExtensions.AddDefaultHostConfigurationSources(Configuration, settings.Args); + Configuration.AddEnvironmentVariables(prefix: "DOTNET_"); } - else + + Initialize(settings, out _hostBuilderContext, out _environment, out _logging); + + ServiceProviderOptions? serviceProviderOptions = null; + if (!settings.DisableDefaults) { - // Command line args are added even when DisableDefaults=true. If the caller didn't want settings.Args applied, - // they wouldn't have set them on the settings. - HostingHostBuilderExtensions.AddCommandLineConfig(Configuration, settings.Args); + HostingHostBuilderExtensions.ApplyDefaultAppConfiguration(_hostBuilderContext, Configuration, settings.Args); + HostingHostBuilderExtensions.AddDefaultServices(_hostBuilderContext, Services); + serviceProviderOptions = HostingHostBuilderExtensions.CreateDefaultServiceProviderOptions(_hostBuilderContext); } + _createServiceProvider = () => + { + // Call _configureContainer in case anyone adds callbacks via HostBuilderAdapter.ConfigureContainer() during build. + // Otherwise, this no-ops. + _configureContainer(Services); + return serviceProviderOptions is null ? Services.BuildServiceProvider() : Services.BuildServiceProvider(serviceProviderOptions); + }; + } + + internal HostApplicationBuilder(HostApplicationBuilderSettings? settings, bool empty) + { + Debug.Assert(empty, "should only be called with empty: true"); + + settings ??= new HostApplicationBuilderSettings(); + Configuration = settings.Configuration ?? new ConfigurationManager(); + + Initialize(settings, out _hostBuilderContext, out _environment, out _logging); + + _createServiceProvider = () => + { + // Call _configureContainer in case anyone adds callbacks via HostBuilderAdapter.ConfigureContainer() during build. + // Otherwise, this no-ops. + _configureContainer(Services); + return Services.BuildServiceProvider(); + }; + } + + private void Initialize(HostApplicationBuilderSettings settings, out HostBuilderContext hostBuilderContext, out IHostEnvironment environment, out LoggingBuilder logging) + { + // Command line args are added even when settings.DisableDefaults == true. If the caller didn't want settings.Args applied, + // they wouldn't have set them on the settings. + HostingHostBuilderExtensions.AddCommandLineConfig(Configuration, settings.Args); + // HostApplicationBuilderSettings override all other config sources. List>? optionList = null; if (settings.ApplicationName is not null) @@ -124,46 +163,29 @@ public HostApplicationBuilder(HostApplicationBuilderSettings? settings) Configuration.SetFileProvider(physicalFileProvider); - _hostBuilderContext = new HostBuilderContext(new Dictionary()) + hostBuilderContext = new HostBuilderContext(new Dictionary()) { HostingEnvironment = hostingEnvironment, Configuration = Configuration, }; - Environment = hostingEnvironment; + environment = hostingEnvironment; HostBuilder.PopulateServiceCollection( Services, - _hostBuilderContext, + hostBuilderContext, hostingEnvironment, physicalFileProvider, Configuration, () => _appServices!); - Logging = new LoggingBuilder(Services); - - ServiceProviderOptions? serviceProviderOptions = null; - - if (!settings.DisableDefaults) - { - HostingHostBuilderExtensions.ApplyDefaultAppConfiguration(_hostBuilderContext, Configuration, settings.Args); - HostingHostBuilderExtensions.AddDefaultServices(_hostBuilderContext, Services); - serviceProviderOptions = HostingHostBuilderExtensions.CreateDefaultServiceProviderOptions(_hostBuilderContext); - } - - _createServiceProvider = () => - { - // Call _configureContainer in case anyone adds callbacks via HostBuilderAdapter.ConfigureContainer() during build. - // Otherwise, this no-ops. - _configureContainer(Services); - return serviceProviderOptions is null ? Services.BuildServiceProvider() : Services.BuildServiceProvider(serviceProviderOptions); - }; + logging = new LoggingBuilder(Services); } /// /// Provides information about the hosting environment an application is running in. /// - public IHostEnvironment Environment { get; } + public IHostEnvironment Environment => _environment; /// /// A collection of services for the application to compose. This is useful for adding user provided or framework provided services. @@ -178,7 +200,7 @@ public HostApplicationBuilder(HostApplicationBuilderSettings? settings) /// /// A collection of logging providers for the application to compose. This is useful for adding new logging providers. /// - public ILoggingBuilder Logging { get; } + public ILoggingBuilder Logging => _logging; /// /// Registers a instance to be used to create the . diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs index c738c47e9af32..db53bb4ab319d 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/HostingHostBuilderExtensions.cs @@ -201,7 +201,9 @@ public static IHostBuilder ConfigureDefaults(this IHostBuilder builder, string[] private static void ApplyDefaultHostConfiguration(IConfigurationBuilder hostConfigBuilder, string[]? args) { SetDefaultContentRoot(hostConfigBuilder); - AddDefaultHostConfigurationSources(hostConfigBuilder, args); + + hostConfigBuilder.AddEnvironmentVariables(prefix: "DOTNET_"); + AddCommandLineConfig(hostConfigBuilder, args); } internal static void SetDefaultContentRoot(IConfigurationBuilder hostConfigBuilder) @@ -224,12 +226,6 @@ internal static void SetDefaultContentRoot(IConfigurationBuilder hostConfigBuild } } - internal static void AddDefaultHostConfigurationSources(IConfigurationBuilder hostConfigBuilder, string[]? args) - { - hostConfigBuilder.AddEnvironmentVariables(prefix: "DOTNET_"); - AddCommandLineConfig(hostConfigBuilder, args); - } - internal static void ApplyDefaultAppConfiguration(HostBuilderContext hostingContext, IConfigurationBuilder appConfigBuilder, string[]? args) { IHostEnvironment env = hostingContext.HostingEnvironment; diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs index edd226bb4aa97..d2167ae3697f8 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderTests.cs @@ -19,10 +19,60 @@ namespace Microsoft.Extensions.Hosting.Tests { public class HostApplicationBuilderTests { - [Fact] - public void DefaultConfigIsMutable() + public delegate HostApplicationBuilder CreateBuilderFunc(); + public delegate HostApplicationBuilder CreateBuilderSettingsFunc(HostApplicationBuilderSettings settings); + + private static HostApplicationBuilder CreateNoDefaultsBuilder() => + new HostApplicationBuilder(new HostApplicationBuilderSettings + { + DisableDefaults = true, + }); + private static HostApplicationBuilder CreateEmptyBuilder() => Host.CreateEmptyApplicationBuilder(settings: null); + + public static IEnumerable CreateNoDefaultsBuilderFuncs + { + get + { + yield return new[] { (CreateBuilderFunc)CreateNoDefaultsBuilder }; + yield return new[] { (CreateBuilderFunc)CreateEmptyBuilder }; + } + } + + private static HostApplicationBuilder CreateBuilderSettingsConstructor(HostApplicationBuilderSettings settings) => + new HostApplicationBuilder(settings); + private static HostApplicationBuilder CreateBuilderSettings(HostApplicationBuilderSettings settings) + => Host.CreateApplicationBuilder(settings); + private static HostApplicationBuilder CreateEmptyBuilderSettings(HostApplicationBuilderSettings settings) + => Host.CreateEmptyApplicationBuilder(settings); + + public static IEnumerable CreateBuilderSettingsFuncs + { + get + { + yield return new[] { (CreateBuilderSettingsFunc)CreateBuilderSettingsConstructor }; + yield return new[] { (CreateBuilderSettingsFunc)CreateBuilderSettings }; + yield return new[] { (CreateBuilderSettingsFunc)CreateEmptyBuilderSettings }; + } + } + + public static IEnumerable CreateBuilderDisableDefaultsData + { + get + { + foreach (bool disableDefaults in new[] { true, false }) + { + yield return new object[] { (CreateBuilderSettingsFunc)CreateBuilderSettingsConstructor, disableDefaults }; + yield return new object[] { (CreateBuilderSettingsFunc)CreateBuilderSettings, disableDefaults }; + yield return new object[] { (CreateBuilderSettingsFunc)CreateEmptyBuilderSettings, disableDefaults }; + } + } + } + + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void DefaultConfigIsMutable(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); builder.Configuration["key1"] = "value1"; @@ -72,7 +122,7 @@ public void BuildFiresEvents() using var _ = DiagnosticListener.AllListeners.Subscribe(listener); - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = CreateNoDefaultsBuilder(); IHost host = builder.Build(); Assert.NotNull(hostBuilderFromEvent); @@ -107,7 +157,7 @@ public void ChangingEnvironmentWithDiagnosticListenerIsNotSupported() using var _ = DiagnosticListener.AllListeners.Subscribe(listener); - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = CreateNoDefaultsBuilder(); Assert.Throws(() => builder.Build()); }); } @@ -136,7 +186,7 @@ public void CanConfigureContainerWithDiagnosticListener() using var _ = DiagnosticListener.AllListeners.Subscribe(listener); - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = CreateNoDefaultsBuilder(); using IHost host = builder.Build(); var fakeServices = host.Services.GetRequiredService(); @@ -144,10 +194,11 @@ public void CanConfigureContainerWithDiagnosticListener() }); } - [Fact] - public void CanConfigureAppConfigurationAndRetrieveFromDI() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void CanConfigureAppConfigurationAndRetrieveFromDI(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); builder.Configuration.AddInMemoryCollection( new KeyValuePair[] @@ -180,10 +231,11 @@ public void CanConfigureAppConfigurationAndRetrieveFromDI() Assert.Equal("value3", config["key2"]); } - [Fact] - public void CanConfigureAppConfigurationFromFile() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void CanConfigureAppConfigurationFromFile(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); builder.Configuration.AddJsonFile("appSettings.json", optional: false); @@ -196,10 +248,11 @@ public void CanConfigureAppConfigurationFromFile() Assert.Equal("value", config["key"]); } - [Fact] - public void DisableDefaultIHostEnvironmentValues() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void DisableDefaultIHostEnvironmentValues(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); Assert.Equal(Environments.Production, builder.Environment.EnvironmentName); #if NETCOREAPP @@ -230,9 +283,8 @@ public void DisableDefaultIHostEnvironmentValues() } [Theory] - [InlineData(true)] - [InlineData(false)] - public void ConfigurationSettingCanInfluenceEnvironment(bool disableDefaults) + [MemberData(nameof(CreateBuilderDisableDefaultsData))] + public void ConfigurationSettingCanInfluenceEnvironment(CreateBuilderSettingsFunc createBuilder, bool disableDefaults) { var tempPath = CreateTempSubdirectory(); @@ -247,7 +299,7 @@ public void ConfigurationSettingCanInfluenceEnvironment(bool disableDefaults) new(HostDefaults.ContentRootKey, tempPath) }); - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + var builder = createBuilder(new HostApplicationBuilderSettings { DisableDefaults = disableDefaults, Configuration = config, @@ -279,9 +331,8 @@ public void ConfigurationSettingCanInfluenceEnvironment(bool disableDefaults) } [Theory] - [InlineData(true)] - [InlineData(false)] - public void DirectSettingsOverrideConfigurationSetting(bool disableDefaults) + [MemberData(nameof(CreateBuilderDisableDefaultsData))] + public void DirectSettingsOverrideConfigurationSetting(CreateBuilderSettingsFunc createBuilder, bool disableDefaults) { var tempPath = CreateTempSubdirectory(); @@ -295,7 +346,7 @@ public void DirectSettingsOverrideConfigurationSetting(bool disableDefaults) new(HostDefaults.EnvironmentKey, "EnvA" ), }); - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + var builder = createBuilder(new HostApplicationBuilderSettings { DisableDefaults = disableDefaults, Configuration = config, @@ -353,8 +404,9 @@ private static string EnsureTrailingSlash(string path) return path; } - [Fact] - public void ChangingConfigurationPostBuilderConsturctionDoesNotChangeEnvironment() + [Theory] + [MemberData(nameof(CreateBuilderSettingsFuncs))] + public void ChangingConfigurationPostBuilderConstructionDoesNotChangeEnvironment(CreateBuilderSettingsFunc createBuilder) { using var config = new ConfigurationManager(); @@ -364,7 +416,7 @@ public void ChangingConfigurationPostBuilderConsturctionDoesNotChangeEnvironment new(HostDefaults.EnvironmentKey, "EnvA" ), }); - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + var builder = createBuilder(new HostApplicationBuilderSettings { DisableDefaults = true, Configuration = config, @@ -389,16 +441,18 @@ public void ChangingConfigurationPostBuilderConsturctionDoesNotChangeEnvironment Assert.Equal("EnvA", hostEnvironmentFromServices.EnvironmentName); } - [Fact] - public void BuildAndDispose() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void BuildAndDispose(CreateBuilderFunc createBuilder) { - using IHost host = CreateEmptyBuilder().Build(); + using IHost host = createBuilder().Build(); } - [Fact] - public void ContentRootConfiguresBasePath() + [Theory] + [MemberData(nameof(CreateBuilderSettingsFuncs))] + public void ContentRootConfiguresBasePath(CreateBuilderSettingsFunc createBuilder) { - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + var builder = createBuilder(new HostApplicationBuilderSettings { DisableDefaults = true, ContentRootPath = "/", @@ -408,8 +462,9 @@ public void ContentRootConfiguresBasePath() Assert.Equal("/", host.Services.GetService().ContentRootPath); } - [Fact] - public void HostConfigParametersReadCorrectly() + [Theory] + [MemberData(nameof(CreateBuilderSettingsFuncs))] + public void HostConfigParametersReadCorrectly(CreateBuilderSettingsFunc createBuilder) { var parameters = new Dictionary() { @@ -421,7 +476,7 @@ public void HostConfigParametersReadCorrectly() var config = new ConfigurationManager(); config.AddInMemoryCollection(parameters); - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + var builder = createBuilder(new HostApplicationBuilderSettings { DisableDefaults = true, Configuration = config @@ -439,10 +494,11 @@ public void HostConfigParametersReadCorrectly() Assert.Equal(Path.GetFullPath("."), env.ContentRootPath); } - [Fact] - public void RelativeContentRootIsResolved() + [Theory] + [MemberData(nameof(CreateBuilderSettingsFuncs))] + public void RelativeContentRootIsResolved(CreateBuilderSettingsFunc createBuilder) { - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + var builder = createBuilder(new HostApplicationBuilderSettings { DisableDefaults = true, ContentRootPath = "testroot", @@ -452,10 +508,11 @@ public void RelativeContentRootIsResolved() Assert.EndsWith(Path.DirectorySeparatorChar + "testroot", builder.Environment.ContentRootPath); } - [Fact] - public void DisableDefaultContentRootIsApplicationBasePath() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void DisableDefaultContentRootIsApplicationBasePath(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); Assert.Equal(AppContext.BaseDirectory, builder.Environment.ContentRootPath); } @@ -466,10 +523,11 @@ public void DefaultContentRootIsCurrentDirectory() Assert.Equal(Directory.GetCurrentDirectory(), builder.Environment.ContentRootPath); } - [Fact] - public void DisableDefaultServicesAreAvailable() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void DisableDefaultServicesAreAvailable(CreateBuilderFunc createBuilder) { - using IHost host = CreateEmptyBuilder().Build(); + using IHost host = createBuilder().Build(); #pragma warning disable CS0618 // Type or member is obsolete Assert.NotNull(host.Services.GetRequiredService()); @@ -513,10 +571,11 @@ public void CanConfigureHostOptionsWithDefaults(BackgroundServiceExceptionBehavi Assert.Equal(testShutdown, hostOptions.ShutdownTimeout); } - [Fact] - public void ConfigureDefaultServiceProvider() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void ConfigureDefaultServiceProvider(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); builder.Services.AddTransient(); builder.Services.AddScoped(); @@ -533,10 +592,11 @@ public void ConfigureDefaultServiceProvider() Assert.Throws(() => { host.Services.GetRequiredService(); }); } - [Fact] - public void ConfigureCustomServiceProvider() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void ConfigureCustomServiceProvider(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); builder.Services.AddTransient(); builder.Services.AddScoped(); @@ -550,10 +610,11 @@ public void ConfigureCustomServiceProvider() } - [Fact] - public void Build_DoesNotAllowBuildingMuiltipleTimes() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void Build_DoesNotAllowBuildingMultipleTimes(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); using (builder.Build()) { var ex = Assert.Throws(() => builder.Build()); @@ -561,10 +622,11 @@ public void Build_DoesNotAllowBuildingMuiltipleTimes() } } - [Fact] - public void SetsFullPathToContentRoot() + [Theory] + [MemberData(nameof(CreateBuilderSettingsFuncs))] + public void SetsFullPathToContentRoot(CreateBuilderSettingsFunc createBuilder) { - var builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + var builder = createBuilder(new HostApplicationBuilderSettings { DisableDefaults = true, ContentRootPath = Path.GetFullPath(".") @@ -577,10 +639,11 @@ public void SetsFullPathToContentRoot() Assert.IsAssignableFrom(env.ContentRootFileProvider); } - [Fact] - public void HostServicesSameServiceProviderAsInHostBuilder() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void HostServicesSameServiceProviderAsInHostBuilder(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); using IHost host = builder.Build(); Type type = builder.GetType(); @@ -590,10 +653,11 @@ public void HostServicesSameServiceProviderAsInHostBuilder() } - [Fact] - public void HostApplicationBuilderThrowsExceptionIfServicesAlreadyBuilt() + [Theory] + [MemberData(nameof(CreateNoDefaultsBuilderFuncs))] + public void HostApplicationBuilderThrowsExceptionIfServicesAlreadyBuilt(CreateBuilderFunc createBuilder) { - HostApplicationBuilder builder = CreateEmptyBuilder(); + HostApplicationBuilder builder = createBuilder(); using IHost host = builder.Build(); Assert.Throws(() => builder.Services.AddSingleton(new ServiceA())); @@ -604,11 +668,10 @@ public void HostApplicationBuilderThrowsExceptionIfServicesAlreadyBuilt() } [Theory] - [InlineData(true)] - [InlineData(false)] - public void RespectsArgsWhenDisableDefaults(bool disableDefaults) + [MemberData(nameof(CreateBuilderDisableDefaultsData))] + public void RespectsArgsWhenDisableDefaults(CreateBuilderSettingsFunc createBuilder, bool disableDefaults) { - HostApplicationBuilder builder = new HostApplicationBuilder(new HostApplicationBuilderSettings + HostApplicationBuilder builder = createBuilder(new HostApplicationBuilderSettings { DisableDefaults = disableDefaults, Args = new string[] { "mySetting=settingValue" } @@ -620,14 +683,6 @@ public void RespectsArgsWhenDisableDefaults(bool disableDefaults) Assert.Equal("settingValue", config["mySetting"]); } - private static HostApplicationBuilder CreateEmptyBuilder() - { - return new HostApplicationBuilder(new HostApplicationBuilderSettings - { - DisableDefaults = true, - }); - } - private class HostingListener : IObserver, IObserver> { private IDisposable? _disposable;