From 4efa6a428b0872820e70e086813cf891212f1469 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 16 Oct 2014 11:44:52 -0700 Subject: [PATCH] Support IServiceProvider ConfigureServices() --- .../Startup/StartupLoader.cs | 38 +++++++++----- .../Fakes/Startup.cs | 49 +++++++++++++++++++ .../StartupManagerTests.cs | 22 +++++++++ 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.AspNet.Hosting/Startup/StartupLoader.cs b/src/Microsoft.AspNet.Hosting/Startup/StartupLoader.cs index 7658009466..6e9591949b 100644 --- a/src/Microsoft.AspNet.Hosting/Startup/StartupLoader.cs +++ b/src/Microsoft.AspNet.Hosting/Startup/StartupLoader.cs @@ -43,17 +43,19 @@ namespace Microsoft.AspNet.Hosting.Startup } return null; } - if (returnType != null && methodInfo.ReturnType != returnType) { - throw new Exception(string.Format("TODO: {0} method does not return " + returnType.Name, - methodInfo.Name)); + if (required) + { + throw new Exception(string.Format("TODO: {0} method does not return " + returnType.Name, + methodInfo.Name)); + } + return null; } - return methodInfo; } - private void Invoke(MethodInfo methodInfo, object instance, IApplicationBuilder builder, IServiceCollection services = null) + private object Invoke(MethodInfo methodInfo, object instance, IApplicationBuilder builder, IServiceCollection services = null) { var parameterInfos = methodInfo.GetParameters(); var parameters = new object[parameterInfos.Length]; @@ -84,7 +86,7 @@ namespace Microsoft.AspNet.Hosting.Startup } } } - methodInfo.Invoke(instance, parameters); + return methodInfo.Invoke(instance, parameters); } public Action LoadStartup( @@ -137,8 +139,8 @@ namespace Microsoft.AspNet.Hosting.Startup } var configureMethod = FindMethod(type, "Configure{0}", environmentName, typeof(void), required: true); - // TODO: accept IServiceProvider method as well? - var servicesMethod = FindMethod(type, "Configure{0}Services", environmentName, typeof(void), required: false); + var servicesMethod = FindMethod(type, "Configure{0}Services", environmentName, typeof(IServiceProvider), required: false) + ?? FindMethod(type, "Configure{0}Services", environmentName, typeof(void), required: false); object instance = null; if (!configureMethod.IsStatic || (servicesMethod != null && !servicesMethod.IsStatic)) @@ -149,12 +151,22 @@ namespace Microsoft.AspNet.Hosting.Startup { if (servicesMethod != null) { - var services = new ServiceCollection(); - services.Add(OptionsServices.GetDefaultServices()); - Invoke(servicesMethod, instance, builder, services); - if (builder != null) + if (servicesMethod.ReturnType == typeof(IServiceProvider)) { - builder.ApplicationServices = services.BuildServiceProvider(builder.ApplicationServices); + // IServiceProvider ConfigureServices() + builder.ApplicationServices = (Invoke(servicesMethod, instance, builder) as IServiceProvider) + ?? builder.ApplicationServices; + } + else + { + // void ConfigureServices(IServiceCollection) + var services = new ServiceCollection(); + services.Add(OptionsServices.GetDefaultServices()); + Invoke(servicesMethod, instance, builder, services); + if (builder != null) + { + builder.ApplicationServices = services.BuildServiceProvider(builder.ApplicationServices); + } } } Invoke(configureMethod, instance, builder); diff --git a/test/Microsoft.AspNet.Hosting.Tests/Fakes/Startup.cs b/test/Microsoft.AspNet.Hosting.Tests/Fakes/Startup.cs index 6f97e4ceda..dab52127bd 100644 --- a/test/Microsoft.AspNet.Hosting.Tests/Fakes/Startup.cs +++ b/test/Microsoft.AspNet.Hosting.Tests/Fakes/Startup.cs @@ -3,6 +3,9 @@ using Microsoft.AspNet.Builder; using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.DependencyInjection.Fallback; +using Microsoft.Framework.OptionsModel; +using System; namespace Microsoft.AspNet.Hosting.Fakes { @@ -44,6 +47,52 @@ namespace Microsoft.AspNet.Hosting.Fakes }); } + public static IServiceProvider ConfigureStaticProviderServices() + { + var services = new ServiceCollection(); + services.Add(OptionsServices.GetDefaultServices()); + services.Configure(o => + { + o.Configured = true; + o.Environment = "StaticProvider"; + }); + return services.BuildServiceProvider(); + } + + public static IServiceProvider ConfigureFallbackProviderServices(IServiceProvider fallback) + { + return fallback; + } + + public static IServiceProvider ConfigureNullServices() + { + return null; + } + + public IServiceProvider ConfigureProviderServices() + { + var services = new ServiceCollection(); + services.Add(OptionsServices.GetDefaultServices()); + services.Configure(o => + { + o.Configured = true; + o.Environment = "Provider"; + }); + return services.BuildServiceProvider(); + } + + public IServiceProvider ConfigureProviderArgsServices(IApplicationBuilder me) + { + var services = new ServiceCollection(); + services.Add(OptionsServices.GetDefaultServices()); + services.Configure(o => + { + o.Configured = true; + o.Environment = "ProviderArgs"; + }); + return services.BuildServiceProvider(); + } + public virtual void Configure(IApplicationBuilder builder) { } diff --git a/test/Microsoft.AspNet.Hosting.Tests/StartupManagerTests.cs b/test/Microsoft.AspNet.Hosting.Tests/StartupManagerTests.cs index 2d73f17c22..6a7527e749 100644 --- a/test/Microsoft.AspNet.Hosting.Tests/StartupManagerTests.cs +++ b/test/Microsoft.AspNet.Hosting.Tests/StartupManagerTests.cs @@ -40,6 +40,9 @@ namespace Microsoft.AspNet.Hosting [InlineData("Dev")] [InlineData("Retail")] [InlineData("Static")] + [InlineData("StaticProvider")] + [InlineData("Provider")] + [InlineData("ProviderArgs")] public void StartupClassAddsConfigureServicesToApplicationServices(string environment) { var serviceCollection = new ServiceCollection(); @@ -59,6 +62,25 @@ namespace Microsoft.AspNet.Hosting Assert.Equal(environment, options.Environment); } + [Theory] + [InlineData("Null")] + [InlineData("FallbackProvider")] + public void StartupClassConfigureServicesThatFallsbackToApplicationServices(string env) + { + var serviceCollection = new ServiceCollection(); + serviceCollection.Add(HostingServices.GetDefaultServices()); + var services = serviceCollection.BuildServiceProvider(); + var manager = services.GetService(); + + var startup = manager.LoadStartup("Microsoft.AspNet.Hosting.Tests", env); + + var app = new ApplicationBuilder(services); + + startup.Invoke(app); + + Assert.Equal(services, app.ApplicationServices); + } + [Fact] public void StartupClassWithConfigureServicesAndUseServicesAddsBothToServices() {