Making Razor compilation cache replaceable (#7780)

This commit is contained in:
Sébastien Ros 2018-05-15 11:36:47 -07:00 committed by GitHub
parent d9f035ad7c
commit 19d82928ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 40 additions and 3 deletions

View File

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
{
/// <summary>
/// Provides an instance of <see cref="IMemoryCache"/> that is used to store compiled Razor views.
/// </summary>
public interface IViewCompilationMemoryCacheProvider
{
IMemoryCache CompilationMemoryCache { get; }
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
{
internal class RazorViewCompilationMemoryCacheProvider : IViewCompilationMemoryCacheProvider
{
IMemoryCache IViewCompilationMemoryCacheProvider.CompilationMemoryCache { get; } = new MemoryCache(new MemoryCacheOptions());
}
}

View File

@ -172,6 +172,7 @@ namespace Microsoft.Extensions.DependencyInjection
return viewEngine; return viewEngine;
}); });
services.TryAddSingleton<IViewCompilerProvider, RazorViewCompilerProvider>(); services.TryAddSingleton<IViewCompilerProvider, RazorViewCompilerProvider>();
services.TryAddSingleton<IViewCompilationMemoryCacheProvider, RazorViewCompilationMemoryCacheProvider>();
// In the default scenario the following services are singleton by virtue of being initialized as part of // In the default scenario the following services are singleton by virtue of being initialized as part of
// creating the singleton RazorViewEngine instance. // creating the singleton RazorViewEngine instance.

View File

@ -34,9 +34,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
private readonly IFileProvider _fileProvider; private readonly IFileProvider _fileProvider;
private readonly RazorProjectEngine _projectEngine; private readonly RazorProjectEngine _projectEngine;
private readonly Action<RoslynCompilationContext> _compilationCallback; private readonly Action<RoslynCompilationContext> _compilationCallback;
private readonly IMemoryCache _cache;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly CSharpCompiler _csharpCompiler; private readonly CSharpCompiler _csharpCompiler;
private readonly IMemoryCache _cache;
public RazorViewCompiler( public RazorViewCompiler(
IFileProvider fileProvider, IFileProvider fileProvider,
@ -44,6 +44,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
CSharpCompiler csharpCompiler, CSharpCompiler csharpCompiler,
Action<RoslynCompilationContext> compilationCallback, Action<RoslynCompilationContext> compilationCallback,
IList<CompiledViewDescriptor> precompiledViews, IList<CompiledViewDescriptor> precompiledViews,
IMemoryCache cache,
ILogger logger) ILogger logger)
{ {
if (fileProvider == null) if (fileProvider == null)
@ -82,11 +83,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
_compilationCallback = compilationCallback; _compilationCallback = compilationCallback;
_logger = logger; _logger = logger;
_normalizedPathCache = new ConcurrentDictionary<string, string>(StringComparer.Ordinal); _normalizedPathCache = new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
// This is our L0 cache, and is a durable store. Views migrate into the cache as they are requested // This is our L0 cache, and is a durable store. Views migrate into the cache as they are requested
// from either the set of known precompiled views, or by being compiled. // from either the set of known precompiled views, or by being compiled.
_cache = new MemoryCache(new MemoryCacheOptions()); _cache = cache;
// We need to validate that the all of the precompiled views are unique by path (case-insenstive). // We need to validate that the all of the precompiled views are unique by path (case-insenstive).
// We do this because there's no good way to canonicalize paths on windows, and it will create // We do this because there's no good way to canonicalize paths on windows, and it will create

View File

@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
private readonly ApplicationPartManager _applicationPartManager; private readonly ApplicationPartManager _applicationPartManager;
private readonly IRazorViewEngineFileProviderAccessor _fileProviderAccessor; private readonly IRazorViewEngineFileProviderAccessor _fileProviderAccessor;
private readonly CSharpCompiler _csharpCompiler; private readonly CSharpCompiler _csharpCompiler;
private readonly IViewCompilationMemoryCacheProvider _compilationMemoryCacheProvider;
private readonly RazorViewEngineOptions _viewEngineOptions; private readonly RazorViewEngineOptions _viewEngineOptions;
private readonly ILogger<RazorViewCompiler> _logger; private readonly ILogger<RazorViewCompiler> _logger;
private readonly Func<IViewCompiler> _createCompiler; private readonly Func<IViewCompiler> _createCompiler;
@ -32,12 +33,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
IRazorViewEngineFileProviderAccessor fileProviderAccessor, IRazorViewEngineFileProviderAccessor fileProviderAccessor,
CSharpCompiler csharpCompiler, CSharpCompiler csharpCompiler,
IOptions<RazorViewEngineOptions> viewEngineOptionsAccessor, IOptions<RazorViewEngineOptions> viewEngineOptionsAccessor,
IViewCompilationMemoryCacheProvider compilationMemoryCacheProvider,
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory)
{ {
_applicationPartManager = applicationPartManager; _applicationPartManager = applicationPartManager;
_razorProjectEngine = razorProjectEngine; _razorProjectEngine = razorProjectEngine;
_fileProviderAccessor = fileProviderAccessor; _fileProviderAccessor = fileProviderAccessor;
_csharpCompiler = csharpCompiler; _csharpCompiler = csharpCompiler;
_compilationMemoryCacheProvider = compilationMemoryCacheProvider;
_viewEngineOptions = viewEngineOptionsAccessor.Value; _viewEngineOptions = viewEngineOptionsAccessor.Value;
_logger = loggerFactory.CreateLogger<RazorViewCompiler>(); _logger = loggerFactory.CreateLogger<RazorViewCompiler>();
@ -74,6 +77,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
_csharpCompiler, _csharpCompiler,
_viewEngineOptions.CompilationCallback, _viewEngineOptions.CompilationCallback,
feature.ViewDescriptors, feature.ViewDescriptors,
_compilationMemoryCacheProvider.CompilationMemoryCache,
_logger); _logger);
} }
} }

View File

@ -4,6 +4,7 @@
using System; using System;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
@ -39,6 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
accessor, accessor,
new CSharpCompiler(referenceManager, Mock.Of<IHostingEnvironment>()), new CSharpCompiler(referenceManager, Mock.Of<IHostingEnvironment>()),
options, options,
new RazorViewCompilationMemoryCacheProvider(),
NullLoggerFactory.Instance); NullLoggerFactory.Instance);
// Act & Assert // Act & Assert

View File

@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Razor.Hosting;
using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Emit;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Moq; using Moq;
@ -875,7 +876,7 @@ this should fail";
Action<RoslynCompilationContext> compilationCallback, Action<RoslynCompilationContext> compilationCallback,
IList<CompiledViewDescriptor> precompiledViews, IList<CompiledViewDescriptor> precompiledViews,
Func<string, CompiledViewDescriptor> compile = null) : Func<string, CompiledViewDescriptor> compile = null) :
base(fileProvider, projectEngine, csharpCompiler, compilationCallback, precompiledViews, NullLogger.Instance) base(fileProvider, projectEngine, csharpCompiler, compilationCallback, precompiledViews, new MemoryCache(new MemoryCacheOptions()), NullLogger.Instance)
{ {
Compile = compile; Compile = compile;
if (Compile == null) if (Compile == null)