diff --git a/samples/MvcSample.Web/Startup.cs b/samples/MvcSample.Web/Startup.cs index aa0981dfaf..8b55efdf9f 100644 --- a/samples/MvcSample.Web/Startup.cs +++ b/samples/MvcSample.Web/Startup.cs @@ -61,8 +61,7 @@ namespace MvcSample.Web // Create the container and use the default application services as a fallback AutofacRegistration.Populate( builder, - services, - fallbackServiceProvider: app.ApplicationServices); + services); builder.RegisterModule(); diff --git a/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs b/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs index 3b00f894d8..66ed6c8733 100644 --- a/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs +++ b/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs @@ -3,6 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Mvc.Razor; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -26,22 +29,50 @@ namespace Microsoft.AspNet.Mvc public virtual void BeforeCompile(IBeforeCompileContext context) { - var sc = new ServiceCollection(); var appEnv = _appServices.GetRequiredService(); var setup = new RazorViewEngineOptionsSetup(appEnv); var accessor = new OptionsManager(new[] { setup }); + var sc = new ServiceCollection(); sc.AddInstance>(accessor); sc.Add(MvcServices.GetDefaultServices()); - var sp = sc.BuildServiceProvider(_appServices); - var viewCompiler = new RazorPreCompiler(sp); + var viewCompiler = new RazorPreCompiler(BuildFallbackServiceProvider(sc, _appServices)); viewCompiler.CompileViews(context); } public void AfterCompile(IAfterCompileContext context) { } + + // TODO: KILL THIS + private static IServiceProvider BuildFallbackServiceProvider(IEnumerable services, IServiceProvider fallback) + { + var sc = HostingServices.Create(fallback); + sc.Add(services); + + // Build the manifest + var manifestTypes = services.Where(t => t.ServiceType.GetTypeInfo().GenericTypeParameters.Length == 0 + && t.ServiceType != typeof(IServiceManifest) + && t.ServiceType != typeof(IServiceProvider)) + .Select(t => t.ServiceType).Distinct(); + sc.AddInstance(new ServiceManifest(manifestTypes, fallback.GetRequiredService())); + return sc.BuildServiceProvider(); + } + + private class ServiceManifest : IServiceManifest + { + public ServiceManifest(IEnumerable services, IServiceManifest fallback = null) + { + Services = services; + if (fallback != null) + { + Services = Services.Concat(fallback.Services).Distinct(); + } + } + + public IEnumerable Services { get; private set; } + } } } diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/FlushPointTest.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/FlushPointTest.cs index 27f3315c91..b3fb2bec39 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/FlushPointTest.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/FlushPointTest.cs @@ -110,7 +110,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests { var services = new ServiceCollection(); services.AddInstance(waitService); - return services.BuildServiceProvider(_provider); + return TestHelper.CreateServices("RazorWebSite", services); } private string GetTrimmedString(Stream stream) diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/InlineConstraintTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/InlineConstraintTests.cs index 25c897b115..5ccd88259a 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/InlineConstraintTests.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/InlineConstraintTests.cs @@ -8,7 +8,6 @@ using InlineConstraints; using Microsoft.AspNet.Builder; using Microsoft.AspNet.TestHost; using Microsoft.Framework.DependencyInjection; -using Microsoft.Framework.DependencyInjection.Fallback; using Xunit; namespace Microsoft.AspNet.Mvc.FunctionalTests @@ -20,10 +19,9 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests public InlineConstraintTests() { - _provider = TestHelper.CreateServices("InlineConstraintsWebSite"); - _provider = new ServiceCollection() - .AddScoped() - .BuildServiceProvider(_provider); + var services = new ServiceCollection() + .AddScoped(); + _provider = TestHelper.CreateServices("InlineConstraintsWebSite", services); } [Fact] diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/RazorInstrumentationTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/RazorInstrumentationTests.cs index 5ba0e40524..9b5d8e6273 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/RazorInstrumentationTests.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/RazorInstrumentationTests.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Microsoft.AspNet.Builder; using Microsoft.AspNet.TestHost; using Microsoft.Framework.DependencyInjection; -using Microsoft.Framework.DependencyInjection.Fallback; using RazorInstrumentationWebSite; using Xunit; @@ -209,7 +208,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests { var services = new ServiceCollection(); services.AddInstance(pageExecutionContext); - return services.BuildServiceProvider(_services); + return TestHelper.CreateServices("RazorInstrumentationWebsite", services); } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/TestHelper.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/TestHelper.cs index 787f2cd11a..d0e72ba54e 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/TestHelper.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/TestHelper.cs @@ -2,10 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; +using Microsoft.AspNet.Hosting; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection.Fallback; +using Microsoft.Framework.DependencyInjection.ServiceLookup; using Microsoft.Framework.Logging; using Microsoft.Framework.Runtime; using Microsoft.Framework.Runtime.Infrastructure; @@ -17,12 +21,12 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests // Path from Mvc\\test\\Microsoft.AspNet.Mvc.FunctionalTests private static readonly string WebsitesDirectoryPath = Path.Combine("..", "WebSites"); - public static IServiceProvider CreateServices(string applicationWebSiteName) + public static IServiceProvider CreateServices(string applicationWebSiteName, IServiceCollection newServices = null) { - return CreateServices(applicationWebSiteName, WebsitesDirectoryPath); + return CreateServices(applicationWebSiteName, WebsitesDirectoryPath, newServices); } - public static IServiceProvider CreateServices(string applicationWebSiteName, string applicationPath) + public static IServiceProvider CreateServices(string applicationWebSiteName, string applicationPath, IServiceCollection newServices = null) { var originalProvider = CallContextServiceLocator.Locator.ServiceProvider; var appEnvironment = originalProvider.GetRequiredService(); @@ -34,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests // To compensate for this, we need to calculate the original path and override the application // environment value so that components like the view engine work properly in the context of the // test. - var appBasePath = CalculateApplicationBasePath(appEnvironment, applicationWebSiteName, applicationPath); + var appBasePath = CalculateApplicationBasePath(appEnvironment, applicationWebSiteName, applicationPath); var services = new ServiceCollection(); services.AddInstance( @@ -58,7 +62,12 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests typeof(ILoggerFactory), NullLoggerFactory.Instance); - return services.BuildServiceProvider(originalProvider); + if (newServices != null) + { + services.Add(newServices); + } + + return BuildFallbackServiceProvider(services, originalProvider); } // Calculate the path relative to the application base path. @@ -106,5 +115,34 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests CallContextServiceLocator.Locator.ServiceProvider = _originalProvider; } } + + // TODO: Kill this code + private static IServiceProvider BuildFallbackServiceProvider(IEnumerable services, IServiceProvider fallback) + { + var sc = HostingServices.Create(fallback); + sc.Add(services); + + // Build the manifest + var manifestTypes = services.Where(t => t.ServiceType.GetTypeInfo().GenericTypeParameters.Length == 0 + && t.ServiceType != typeof(IServiceManifest) + && t.ServiceType != typeof(IServiceProvider)) + .Select(t => t.ServiceType).Distinct(); + sc.AddInstance(new ServiceManifest(manifestTypes, fallback.GetRequiredService())); + return sc.BuildServiceProvider(); + } + + private class ServiceManifest : IServiceManifest + { + public ServiceManifest(IEnumerable services, IServiceManifest fallback = null) + { + Services = services; + if (fallback != null) + { + Services = Services.Concat(fallback.Services).Distinct(); + } + } + + public IEnumerable Services { get; private set; } + } } } \ No newline at end of file diff --git a/test/WebSites/AutofacWebSite/Startup.cs b/test/WebSites/AutofacWebSite/Startup.cs index 30983055f4..48f6af4464 100644 --- a/test/WebSites/AutofacWebSite/Startup.cs +++ b/test/WebSites/AutofacWebSite/Startup.cs @@ -18,9 +18,8 @@ namespace AutofacWebSite services.AddTransient(); var builder = new ContainerBuilder(); - AutofacRegistration.Populate(builder, - services, - fallbackServiceProvider: app.ApplicationServices); + AutofacRegistration.Populate(builder, + services); var container = builder.Build(); diff --git a/test/WebSites/PrecompilationWebSite/Compiler/PreProcess/RazorPreCompilation.cs b/test/WebSites/PrecompilationWebSite/Compiler/PreProcess/RazorPreCompilation.cs index 52d8a22f9c..712787ad00 100644 --- a/test/WebSites/PrecompilationWebSite/Compiler/PreProcess/RazorPreCompilation.cs +++ b/test/WebSites/PrecompilationWebSite/Compiler/PreProcess/RazorPreCompilation.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Runtime.Versioning; using Microsoft.AspNet.Mvc; +using Microsoft.AspNet.Hosting; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection.Fallback; using Microsoft.Framework.Runtime; @@ -35,10 +36,10 @@ namespace PrecompilationWebSite originalEnvironment, newPath); - var collection = new ServiceCollection(); + var collection = HostingServices.Create(provider); collection.AddInstance(precompilationApplicationEnvironment); - return collection.BuildServiceProvider(provider); + return new DelegatingServiceProvider(provider, collection.BuildServiceProvider()); } private class PrecompilationApplicationEnvironment : IApplicationEnvironment @@ -80,5 +81,23 @@ namespace PrecompilationWebSite get { return _originalApplicationEnvironment.RuntimeFramework; } } } + + private class DelegatingServiceProvider : IServiceProvider + { + private readonly IServiceProvider _fallback; + private readonly IServiceProvider _services; + + public DelegatingServiceProvider(IServiceProvider fallback, IServiceProvider services) + { + _fallback = fallback; + _services = services; + } + + public object GetService(Type serviceType) + { + return _services.GetService(serviceType) ?? _fallback.GetService(serviceType); + } + } + } } \ No newline at end of file