From a5d728cc51f5c026dd62fc7c9a10a07c33e52d85 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 18:21:44 +1100 Subject: [PATCH] Reduce the usage of BuildServiceProvider --- src/Umbraco.Tests.Integration/RuntimeTests.cs | 31 ++++++++++--------- .../UmbracoCoreServiceCollectionExtensions.cs | 22 ++++++------- src/Umbraco.Web.UI.NetCore/Startup.cs | 20 ++++++++++-- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index b12d02ca85..0e11a29b95 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -94,18 +94,18 @@ namespace Umbraco.Tests.Integration public async Task AddUmbracoCore() { var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + var testHelper = new TestHelper(); var hostBuilder = new HostBuilder() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { - var testHelper = new TestHelper(); - - AddRequiredNetCoreServices(services, testHelper); + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -138,12 +138,13 @@ namespace Umbraco.Tests.Integration var hostBuilder = new HostBuilder() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => - { - AddRequiredNetCoreServices(services, testHelper); + { + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -178,11 +179,12 @@ namespace Umbraco.Tests.Integration .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { - AddRequiredNetCoreServices(services, testHelper); + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -223,11 +225,12 @@ namespace Umbraco.Tests.Integration /// /// /// - private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper) + /// + private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper, IWebHostEnvironment webHostEnvironment) { services.AddSingleton(x => testHelper.GetHttpContextAccessor()); // the generic host does add IHostEnvironment but not this one because we are not actually in a web context - services.AddSingleton(x => testHelper.GetWebHostEnvironment()); + services.AddSingleton(x => webHostEnvironment); } [RuntimeLevel(MinLevel = RuntimeLevel.Install)] diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index 20901822e3..d747cb349a 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -26,14 +26,11 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// Adds the Umbraco Configuration requirements /// /// + /// /// - public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services) + public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services, IConfiguration configuration) { - // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured - var serviceProvider = services.BuildServiceProvider(); - var configuration = serviceProvider.GetService(); - if (configuration == null) - throw new InvalidOperationException($"Could not resolve {typeof(IConfiguration)} from the container"); + if (configuration == null) throw new ArgumentNullException(nameof(configuration)); var configsFactory = new AspNetCoreConfigsFactory(configuration); @@ -49,25 +46,27 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// Adds the Umbraco Back Core requirements /// /// + /// /// - public static IServiceCollection AddUmbracoCore(this IServiceCollection services) + public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment) { if (!UmbracoServiceProviderFactory.IsActive) throw new InvalidOperationException("Ensure to add UseUmbraco() in your Program.cs after ConfigureWebHostDefaults to enable Umbraco's service provider factory"); var umbContainer = UmbracoServiceProviderFactory.UmbracoContainer; - return services.AddUmbracoCore(umbContainer, Assembly.GetEntryAssembly()); + return services.AddUmbracoCore(webHostEnvironment, umbContainer, Assembly.GetEntryAssembly()); } /// /// Adds the Umbraco Back Core requirements /// /// + /// /// /// /// - public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly) + public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IRegister umbContainer, Assembly entryAssembly) { if (services is null) throw new ArgumentNullException(nameof(services)); if (umbContainer is null) throw new ArgumentNullException(nameof(umbContainer)); @@ -77,7 +76,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore // we resolve it before the host finishes configuring in the call to CreateCompositionRoot services.AddSingleton(); - CreateCompositionRoot(services, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); + CreateCompositionRoot(services, webHostEnvironment, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); var globalSettings = configs.Global(); var umbracoVersion = new UmbracoVersion(globalSettings); @@ -126,7 +125,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore return coreRuntime; } - private static void CreateCompositionRoot(IServiceCollection services, + private static void CreateCompositionRoot(IServiceCollection services, IWebHostEnvironment webHostEnvironment, out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment, out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { @@ -134,7 +133,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore var serviceProvider = services.BuildServiceProvider(); var httpContextAccessor = serviceProvider.GetRequiredService(); - var webHostEnvironment = serviceProvider.GetRequiredService(); configs = serviceProvider.GetService(); if (configs == null) diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index ab8c6e021c..2753676452 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -16,13 +16,29 @@ namespace Umbraco.Web.UI.BackOffice { public class Startup { + private readonly IWebHostEnvironment _webHostEnvironment; + private readonly IConfiguration _config; + + /// + /// Constructor + /// + /// + /// + /// + /// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337 + /// + public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config) + { + _webHostEnvironment = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment)); + _config = config ?? throw new ArgumentNullException(nameof(config)); + } // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(); + services.AddUmbracoConfiguration(_config); + services.AddUmbracoCore(_webHostEnvironment); services.AddUmbracoWebsite(); }