Stop passing around IServiceProvider in RazorPreCompiler

Fixes #2204
This commit is contained in:
Pranav K 2015-03-23 17:29:23 -07:00
parent 401fd1c833
commit 939fb2ba53
2 changed files with 26 additions and 114 deletions

View File

@ -14,9 +14,7 @@ using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Framework.Caching.Memory; using Microsoft.Framework.Caching.Memory;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.Runtime; using Microsoft.Framework.Runtime;
using Microsoft.Framework.Runtime.Roslyn; using Microsoft.Framework.Runtime.Roslyn;
@ -24,32 +22,16 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
public class RazorPreCompiler public class RazorPreCompiler
{ {
private readonly IFileProvider _fileProvider;
public RazorPreCompiler( public RazorPreCompiler(
[NotNull] IServiceProvider designTimeServiceProvider,
[NotNull] IBeforeCompileContext compileContext,
[NotNull] IMemoryCache precompilationCache,
[NotNull] CompilationSettings compilationSettings)
: this(
compileContext,
designTimeServiceProvider.GetRequiredService<IAssemblyLoadContextAccessor>(),
designTimeServiceProvider.GetRequiredService<IOptions<RazorViewEngineOptions>>(),
precompilationCache,
compilationSettings)
{
}
private RazorPreCompiler(
[NotNull] IBeforeCompileContext compileContext, [NotNull] IBeforeCompileContext compileContext,
[NotNull] IAssemblyLoadContextAccessor loadContextAccessor, [NotNull] IAssemblyLoadContextAccessor loadContextAccessor,
[NotNull] IOptions<RazorViewEngineOptions> optionsAccessor, [NotNull] IFileProvider fileProvider,
[NotNull] IMemoryCache precompilationCache, [NotNull] IMemoryCache precompilationCache,
[NotNull] CompilationSettings compilationSettings) [NotNull] CompilationSettings compilationSettings)
{ {
CompileContext = compileContext; CompileContext = compileContext;
LoadContext = loadContextAccessor.GetLoadContext(GetType().GetTypeInfo().Assembly); LoadContext = loadContextAccessor.GetLoadContext(GetType().GetTypeInfo().Assembly);
_fileProvider = optionsAccessor.Options.FileProvider; FileProvider = fileProvider;
CompilationSettings = compilationSettings; CompilationSettings = compilationSettings;
PreCompilationCache = precompilationCache; PreCompilationCache = precompilationCache;
TagHelperTypeResolver = new PrecompilationTagHelperTypeResolver(CompileContext, LoadContext); TagHelperTypeResolver = new PrecompilationTagHelperTypeResolver(CompileContext, LoadContext);
@ -60,6 +42,8 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary> /// </summary>
public bool GenerateSymbols { get; set; } public bool GenerateSymbols { get; set; }
protected IFileProvider FileProvider { get; }
protected IBeforeCompileContext CompileContext { get; } protected IBeforeCompileContext CompileContext { get; }
protected IAssemblyLoadContext LoadContext { get; } protected IAssemblyLoadContext LoadContext { get; }
@ -200,7 +184,7 @@ namespace Microsoft.AspNet.Mvc.Razor
protected IMvcRazorHost GetRazorHost() protected IMvcRazorHost GetRazorHost()
{ {
var descriptorResolver = new TagHelperDescriptorResolver(TagHelperTypeResolver); var descriptorResolver = new TagHelperDescriptorResolver(TagHelperTypeResolver);
return new MvcRazorHost(new DefaultCodeTreeCache(_fileProvider)) return new MvcRazorHost(new DefaultCodeTreeCache(FileProvider))
{ {
TagHelperDescriptorResolver = descriptorResolver TagHelperDescriptorResolver = descriptorResolver
}; };
@ -213,10 +197,10 @@ namespace Microsoft.AspNet.Mvc.Razor
if (entry != null) if (entry != null)
{ {
cacheSetContext.AddExpirationTrigger(_fileProvider.Watch(fileInfo.RelativePath)); cacheSetContext.AddExpirationTrigger(FileProvider.Watch(fileInfo.RelativePath));
foreach (var path in ViewHierarchyUtility.GetGlobalImportLocations(fileInfo.RelativePath)) foreach (var path in ViewHierarchyUtility.GetGlobalImportLocations(fileInfo.RelativePath))
{ {
cacheSetContext.AddExpirationTrigger(_fileProvider.Watch(path)); cacheSetContext.AddExpirationTrigger(FileProvider.Watch(path));
} }
} }
@ -225,7 +209,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private void GetFileInfosRecursive(string root, List<RelativeFileInfo> razorFiles) private void GetFileInfosRecursive(string root, List<RelativeFileInfo> razorFiles)
{ {
var fileInfos = _fileProvider.GetDirectoryContents(root); var fileInfos = FileProvider.GetDirectoryContents(root);
foreach (var fileInfo in fileInfos) foreach (var fileInfo in fileInfos)
{ {
@ -299,7 +283,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private class PrecompileRazorFileInfoCollection : RazorFileInfoCollection private class PrecompileRazorFileInfoCollection : RazorFileInfoCollection
{ {
public PrecompileRazorFileInfoCollection(string assemblyResourceName, public PrecompileRazorFileInfoCollection(string assemblyResourceName,
string symbolsResourceName, string symbolsResourceName,
IReadOnlyList<RazorFileInfo> fileInfos) IReadOnlyList<RazorFileInfo> fileInfos)
{ {
AssemblyResourceName = assemblyResourceName; AssemblyResourceName = assemblyResourceName;

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Runtime.Versioning; using Microsoft.AspNet.FileProviders;
using Microsoft.AspNet.Mvc.Razor; using Microsoft.AspNet.Mvc.Razor;
using Microsoft.Framework.Caching.Memory; using Microsoft.Framework.Caching.Memory;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
@ -42,29 +42,17 @@ namespace Microsoft.AspNet.Mvc
/// <remarks>Pre-compiles all Razor views in the application.</remarks> /// <remarks>Pre-compiles all Razor views in the application.</remarks>
public virtual void BeforeCompile(IBeforeCompileContext context) public virtual void BeforeCompile(IBeforeCompileContext context)
{ {
var applicationEnvironment = _appServices.GetRequiredService<IApplicationEnvironment>();
var compilerOptionsProvider = _appServices.GetRequiredService<ICompilerOptionsProvider>(); var compilerOptionsProvider = _appServices.GetRequiredService<ICompilerOptionsProvider>();
var compilationSettings = compilerOptionsProvider.GetCompilationSettings(applicationEnvironment); var loadContextAccessor = _appServices.GetRequiredService<IAssemblyLoadContextAccessor>();
var compilationSettings = GetCompilationSettings(compilerOptionsProvider, context.ProjectContext);
var fileProvider = new PhysicalFileProvider(context.ProjectContext.ProjectDirectory);
// Create something similar to a HttpContext.RequestServices provider. Necessary because this class is var viewCompiler = new RazorPreCompiler(
// instantiated in a lower-level "HttpContext.ApplicationServices" context. One important added service context,
// is an IOptions<RazorViewEngineOptions> but use AddMvc() for simplicity and flexibility. loadContextAccessor,
// We also need an IApplicationEnvironment with a base path that matches the containing web site, to fileProvider,
// find the razor files. We don't have a guarantee that the base path of the current application is _memoryCache,
// this site. For example similar functional test changes to the IApplicationEnvironment happen later, compilationSettings)
// after everything is compiled. IOptions<RazorViewEngineOptions> setup initializes the
// RazorViewEngineOptions based on this IApplicationEnvironment implementation.
var directory = context.ProjectContext.ProjectDirectory;
var precompilationApplicationEnvironment = new PrecompilationApplicationEnvironment(
applicationEnvironment,
context.ProjectContext.ProjectDirectory);
var replacedServices = new ServiceCollection();
replacedServices.AddMvc();
replacedServices.AddInstance<IApplicationEnvironment>(precompilationApplicationEnvironment);
var wrappedServices = new WrappingServiceProvider(_appServices, replacedServices);
var viewCompiler = new RazorPreCompiler(wrappedServices, context, _memoryCache, compilationSettings)
{ {
GenerateSymbols = GenerateSymbols GenerateSymbols = GenerateSymbols
}; };
@ -77,74 +65,14 @@ namespace Microsoft.AspNet.Mvc
{ {
} }
private class WrappingServiceProvider : IServiceProvider private static CompilationSettings GetCompilationSettings(
ICompilerOptionsProvider compilerOptionsProvider,
IProjectContext projectContext)
{ {
private readonly IServiceProvider _fallback; return compilerOptionsProvider.GetCompilerOptions(projectContext.Name,
private readonly IServiceProvider _override; projectContext.TargetFramework,
projectContext.Configuration)
// Need full wrap for generics like IOptions .ToCompilationSettings(projectContext.TargetFramework);
public WrappingServiceProvider(IServiceProvider fallback, IServiceCollection replacedServices)
{
_fallback = fallback;
_override = replacedServices.BuildServiceProvider();
}
public object GetService(Type serviceType)
{
return _override.GetService(serviceType) ?? _fallback.GetService(serviceType);
}
}
private class PrecompilationApplicationEnvironment : IApplicationEnvironment
{
private readonly IApplicationEnvironment _originalApplicationEnvironment;
private readonly string _applicationBasePath;
public PrecompilationApplicationEnvironment(IApplicationEnvironment original, string appBasePath)
{
_originalApplicationEnvironment = original;
_applicationBasePath = appBasePath;
}
public string ApplicationName
{
get
{
return _originalApplicationEnvironment.ApplicationName;
}
}
public string Version
{
get
{
return _originalApplicationEnvironment.Version;
}
}
public string ApplicationBasePath
{
get
{
return _applicationBasePath;
}
}
public string Configuration
{
get
{
return _originalApplicationEnvironment.Configuration;
}
}
public FrameworkName RuntimeFramework
{
get
{
return _originalApplicationEnvironment.RuntimeFramework;
}
}
} }
} }
} }