diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/ApplicationLifetime.cs b/src/Microsoft.AspNetCore.Hosting/Internal/ApplicationLifetime.cs index 47d16e9654..958f8b5dcc 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/ApplicationLifetime.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/ApplicationLifetime.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal /// /// Allows consumers to perform cleanup during a graceful shutdown. /// - public class ApplicationLifetime : IApplicationLifetime + public class ApplicationLifetime : IApplicationLifetime, Extensions.Hosting.IApplicationLifetime { private readonly CancellationTokenSource _startedSource = new CancellationTokenSource(); private readonly CancellationTokenSource _stoppingSource = new CancellationTokenSource(); diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/HostingEnvironment.cs b/src/Microsoft.AspNetCore.Hosting/Internal/HostingEnvironment.cs index 34924ab365..1f8d1887d7 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/HostingEnvironment.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/HostingEnvironment.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.FileProviders; namespace Microsoft.AspNetCore.Hosting.Internal { - public class HostingEnvironment : IHostingEnvironment + public class HostingEnvironment : IHostingEnvironment, Extensions.Hosting.IHostingEnvironment { public string EnvironmentName { get; set; } = Hosting.EnvironmentName.Production; diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs b/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs index da74e1d1ea..203cea8137 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs @@ -76,6 +76,11 @@ namespace Microsoft.AspNetCore.Hosting.Internal _applicationServiceCollection = appServices; _hostingServiceProvider = hostingServiceProvider; _applicationServiceCollection.AddSingleton(); + // There's no way to to register multiple service types per definition. See https://github.com/aspnet/DependencyInjection/issues/360 + _applicationServiceCollection.AddSingleton(sp => + { + return sp.GetRequiredService() as Extensions.Hosting.IApplicationLifetime; + }); _applicationServiceCollection.AddSingleton(); } diff --git a/src/Microsoft.AspNetCore.Hosting/Microsoft.AspNetCore.Hosting.csproj b/src/Microsoft.AspNetCore.Hosting/Microsoft.AspNetCore.Hosting.csproj index 67f9152238..830ff401e9 100644 --- a/src/Microsoft.AspNetCore.Hosting/Microsoft.AspNetCore.Hosting.csproj +++ b/src/Microsoft.AspNetCore.Hosting/Microsoft.AspNetCore.Hosting.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs b/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs index f0dede89fd..31f07c6d71 100644 --- a/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs +++ b/src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Hosting /// public class WebHostBuilder : IWebHostBuilder { - private readonly IHostingEnvironment _hostingEnvironment; + private readonly HostingEnvironment _hostingEnvironment; private readonly List> _configureServicesDelegates; private IConfiguration _config; @@ -239,7 +239,8 @@ namespace Microsoft.AspNetCore.Hosting var services = new ServiceCollection(); services.AddSingleton(_options); - services.AddSingleton(_hostingEnvironment); + services.AddSingleton(_hostingEnvironment); + services.AddSingleton(_hostingEnvironment); services.AddSingleton(_context); var builder = new ConfigurationBuilder() diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs index f479c93a3d..a7c358141f 100644 --- a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs +++ b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs @@ -526,6 +526,7 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { Assert.Equal(expected, host.Services.GetService().EnvironmentName); + Assert.Equal(expected, host.Services.GetService().EnvironmentName); } } @@ -568,6 +569,7 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { Assert.Equal("/", host.Services.GetService().ContentRootPath); + Assert.Equal("/", host.Services.GetService().ContentRootPath); } } @@ -581,8 +583,13 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { var basePath = host.Services.GetRequiredService().ContentRootPath; + var basePath2 = host.Services.GetService().ContentRootPath; + Assert.True(Path.IsPathRooted(basePath)); Assert.EndsWith(Path.DirectorySeparatorChar + "testroot", basePath); + + Assert.True(Path.IsPathRooted(basePath2)); + Assert.EndsWith(Path.DirectorySeparatorChar + "testroot", basePath2); } } @@ -596,6 +603,7 @@ namespace Microsoft.AspNetCore.Hosting { var appBase = AppContext.BaseDirectory; Assert.Equal(appBase, host.Services.GetService().ContentRootPath); + Assert.Equal(appBase, host.Services.GetService().ContentRootPath); } } @@ -620,7 +628,9 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { var hostingEnv = host.Services.GetService(); + var hostingEnv2 = host.Services.GetService(); Assert.Equal(typeof(Startup).Assembly.GetName().Name, hostingEnv.ApplicationName); + Assert.Equal(typeof(Startup).Assembly.GetName().Name, hostingEnv2.ApplicationName); } } @@ -634,7 +644,9 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { var hostingEnv = host.Services.GetService(); + var hostingEnv2 = host.Services.GetService(); Assert.Equal(typeof(StartupNoServices).Assembly.GetName().Name, hostingEnv.ApplicationName); + Assert.Equal(typeof(StartupNoServices).Assembly.GetName().Name, hostingEnv2.ApplicationName); } } @@ -1046,7 +1058,7 @@ namespace Microsoft.AspNetCore.Hosting .ConfigureServices(services => services.AddSingleton(loggerProvider.Sink)) .ConfigureLogging((_, lf) => lf.AddProvider(loggerProvider)) .ConfigureAppConfiguration((context, configurationBuilder) => configurationBuilder.AddInMemoryCollection( - new [] + new[] { new KeyValuePair("testhostingstartup:config", "value") })); diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs index 001f267889..70d12561d3 100644 --- a/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs +++ b/test/Microsoft.AspNetCore.Hosting.Tests/WebHostTests.cs @@ -167,6 +167,7 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { var lifetime = host.Services.GetRequiredService(); + var lifetime2 = host.Services.GetRequiredService(); var server = (FakeServer)host.Services.GetRequiredService(); var cts = new CancellationTokenSource(); @@ -175,6 +176,7 @@ namespace Microsoft.AspNetCore.Hosting // Wait on the host to be started lifetime.ApplicationStarted.WaitHandle.WaitOne(); + Assert.True(lifetime2.ApplicationStarted.IsCancellationRequested); Assert.Equal(1, server.StartInstances.Count); Assert.Equal(0, server.StartInstances[0].DisposeCalls); @@ -183,6 +185,7 @@ namespace Microsoft.AspNetCore.Hosting // Wait on the host to shutdown lifetime.ApplicationStopped.WaitHandle.WaitOne(); + Assert.True(lifetime2.ApplicationStopped.IsCancellationRequested); // Wait for RunAsync to finish to guarantee Disposal of WebHost await runInBackground; @@ -408,11 +411,14 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { var applicationLifetime = host.Services.GetService(); + var applicationLifetime2 = host.Services.GetService(); Assert.False(applicationLifetime.ApplicationStarted.IsCancellationRequested); + Assert.False(applicationLifetime2.ApplicationStarted.IsCancellationRequested); await host.StartAsync(); Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested); + Assert.True(applicationLifetime2.ApplicationStarted.IsCancellationRequested); } } @@ -424,17 +430,26 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { var applicationLifetime = host.Services.GetService(); + var applicationLifetime2 = host.Services.GetService(); var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted); var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping); var stopped = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopped); + var started2 = RegisterCallbacksThatThrow(applicationLifetime2.ApplicationStarted); + var stopping2 = RegisterCallbacksThatThrow(applicationLifetime2.ApplicationStopping); + var stopped2 = RegisterCallbacksThatThrow(applicationLifetime2.ApplicationStopped); + await host.StartAsync(); Assert.True(applicationLifetime.ApplicationStarted.IsCancellationRequested); + Assert.True(applicationLifetime2.ApplicationStarted.IsCancellationRequested); Assert.True(started.All(s => s)); + Assert.True(started2.All(s => s)); host.Dispose(); Assert.True(stopping.All(s => s)); + Assert.True(stopping2.All(s => s)); Assert.True(stopped.All(s => s)); + Assert.True(stopped2.All(s => s)); } } @@ -663,18 +678,24 @@ namespace Microsoft.AspNetCore.Hosting .Build()) { var applicationLifetime = host.Services.GetService(); + var applicationLifetime2 = host.Services.GetService(); var started = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStarted); var stopping = RegisterCallbacksThatThrow(applicationLifetime.ApplicationStopping); + var started2 = RegisterCallbacksThatThrow(applicationLifetime2.ApplicationStarted); + var stopping2 = RegisterCallbacksThatThrow(applicationLifetime2.ApplicationStopping); + await host.StartAsync(); Assert.True(events1[0]); Assert.True(events2[0]); Assert.True(started.All(s => s)); + Assert.True(started2.All(s => s)); host.Dispose(); Assert.True(events1[1]); Assert.True(events2[1]); Assert.True(stopping.All(s => s)); + Assert.True(stopping2.All(s => s)); } } @@ -689,7 +710,9 @@ namespace Microsoft.AspNetCore.Hosting { await host.StartAsync(); var env = host.Services.GetService(); + var env2 = host.Services.GetService(); Assert.Equal("Changed", env.EnvironmentName); + Assert.Equal("Changed", env2.EnvironmentName); } } @@ -771,7 +794,9 @@ namespace Microsoft.AspNetCore.Hosting using (var host = CreateBuilder().UseFakeServer().Build()) { var env = host.Services.GetService(); + var env2 = host.Services.GetService(); Assert.Equal(EnvironmentName.Production, env.EnvironmentName); + Assert.Equal(EnvironmentName.Production, env2.EnvironmentName); } } @@ -790,6 +815,8 @@ namespace Microsoft.AspNetCore.Hosting using (var host = CreateBuilder(config).UseFakeServer().Build()) { var env = host.Services.GetService(); + var env2 = host.Services.GetService(); + Assert.Equal(EnvironmentName.Staging, env.EnvironmentName); Assert.Equal(EnvironmentName.Staging, env.EnvironmentName); } } @@ -990,7 +1017,7 @@ namespace Microsoft.AspNetCore.Hosting { private readonly IApplicationLifetime _lifetime; - public TestHostedService(IApplicationLifetime lifetime) + public TestHostedService(IApplicationLifetime lifetime, Extensions.Hosting.IApplicationLifetime lifetime2) { _lifetime = lifetime; }