Use PrecompilationTagHelperTypeResolver to locate TagHelpers during
precompilation. Fixes #2298
This commit is contained in:
parent
894574d04e
commit
2e32ffc004
|
|
@ -1,88 +0,0 @@
|
||||||
// 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 System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading;
|
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
|
||||||
using Microsoft.Dnx.Compilation.CSharp;
|
|
||||||
using Microsoft.Dnx.Runtime;
|
|
||||||
using Microsoft.Framework.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="TagHelperDescriptorResolver"/> used during Razor precompilation.
|
|
||||||
/// </summary>
|
|
||||||
public class PrecompilationTagHelperTypeResolver : TagHelperTypeResolver
|
|
||||||
{
|
|
||||||
private static readonly string TagHelperTypeName = typeof(ITagHelper).FullName;
|
|
||||||
private readonly BeforeCompileContext _compileContext;
|
|
||||||
private readonly IAssemblyLoadContext _loadContext;
|
|
||||||
private object _compilationLock = new object();
|
|
||||||
private bool _assemblyEmited;
|
|
||||||
private TypeInfo[] _exportedTypeInfos;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of <see cref="PrecompilationTagHelperTypeResolver"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="compileContext">The <see cref="BeforeCompileContext"/>.</param>
|
|
||||||
/// <param name="loadContext">The <see cref="IAssemblyLoadContext"/>.</param>
|
|
||||||
public PrecompilationTagHelperTypeResolver([NotNull] BeforeCompileContext compileContext,
|
|
||||||
[NotNull] IAssemblyLoadContext loadContext)
|
|
||||||
{
|
|
||||||
_compileContext = compileContext;
|
|
||||||
_loadContext = loadContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override IEnumerable<TypeInfo> GetExportedTypes([NotNull] AssemblyName assemblyName)
|
|
||||||
{
|
|
||||||
var compilingAssemblyName = _compileContext.Compilation.AssemblyName;
|
|
||||||
if (string.Equals(assemblyName.Name, compilingAssemblyName, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
return LazyInitializer.EnsureInitialized(ref _exportedTypeInfos,
|
|
||||||
ref _assemblyEmited,
|
|
||||||
ref _compilationLock,
|
|
||||||
GetExportedTypesFromCompilation);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetExportedTypesCore(assemblyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<TypeInfo> GetExportedTypesCore(AssemblyName assemblyName)
|
|
||||||
{
|
|
||||||
var assembly = _loadContext.Load(assemblyName.Name);
|
|
||||||
|
|
||||||
return assembly.ExportedTypes.Select(type => type.GetTypeInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
private TypeInfo[] GetExportedTypesFromCompilation()
|
|
||||||
{
|
|
||||||
using (var stream = new MemoryStream())
|
|
||||||
{
|
|
||||||
var assemblyName = string.Join(".", _compileContext.Compilation.AssemblyName,
|
|
||||||
nameof(PrecompilationTagHelperTypeResolver),
|
|
||||||
Path.GetRandomFileName());
|
|
||||||
|
|
||||||
var emitResult = _compileContext.Compilation
|
|
||||||
.WithAssemblyName(assemblyName)
|
|
||||||
.Emit(stream);
|
|
||||||
if (!emitResult.Success)
|
|
||||||
{
|
|
||||||
// Return an empty sequence. Compilation will fail once precompilation completes.
|
|
||||||
return new TypeInfo[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.Position = 0;
|
|
||||||
var assembly = _loadContext.LoadStream(stream, assemblySymbols: null);
|
|
||||||
return assembly.ExportedTypes
|
|
||||||
.Select(type => type.GetTypeInfo())
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,9 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using Microsoft.AspNet.FileProviders;
|
using Microsoft.AspNet.FileProviders;
|
||||||
using Microsoft.Dnx.Compilation.CSharp;
|
using Microsoft.Dnx.Compilation.CSharp;
|
||||||
using Microsoft.Dnx.Runtime;
|
|
||||||
using Microsoft.Framework.Caching.Memory;
|
using Microsoft.Framework.Caching.Memory;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
||||||
|
|
@ -18,20 +16,10 @@ namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class RazorPreCompileModule : ICompileModule
|
public abstract class RazorPreCompileModule : ICompileModule
|
||||||
{
|
{
|
||||||
private readonly IAssemblyLoadContext _loadContext;
|
|
||||||
private readonly object _memoryCacheLookupLock = new object();
|
private readonly object _memoryCacheLookupLock = new object();
|
||||||
private readonly Dictionary<PrecompilationCacheKey, MemoryCache> _memoryCacheLookup =
|
private readonly Dictionary<PrecompilationCacheKey, MemoryCache> _memoryCacheLookup =
|
||||||
new Dictionary<PrecompilationCacheKey, MemoryCache>();
|
new Dictionary<PrecompilationCacheKey, MemoryCache>();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Instantiates a new <see cref="RazorPreCompileModule"/> instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="services">The <see cref="IServiceProvider"/> for the application.</param>
|
|
||||||
public RazorPreCompileModule(IServiceProvider services)
|
|
||||||
{
|
|
||||||
_loadContext = services.GetRequiredService<IAssemblyLoadContext>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value that determines if symbols (.pdb) file for the precompiled views is generated.
|
/// Gets or sets a value that determines if symbols (.pdb) file for the precompiled views is generated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -65,7 +53,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
||||||
|
|
||||||
var viewCompiler = new RazorPreCompiler(
|
var viewCompiler = new RazorPreCompiler(
|
||||||
context,
|
context,
|
||||||
_loadContext,
|
|
||||||
fileProvider,
|
fileProvider,
|
||||||
memoryCache)
|
memoryCache)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,21 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.FileProviders;
|
using Microsoft.AspNet.FileProviders;
|
||||||
using Microsoft.AspNet.Mvc.Internal;
|
using Microsoft.AspNet.Mvc.Internal;
|
||||||
using Microsoft.AspNet.Mvc.Razor.Compilation;
|
using Microsoft.AspNet.Mvc.Razor.Compilation;
|
||||||
using Microsoft.AspNet.Mvc.Razor.Directives;
|
using Microsoft.AspNet.Mvc.Razor.Directives;
|
||||||
using Microsoft.AspNet.Mvc.Razor.Internal;
|
using Microsoft.AspNet.Mvc.Razor.Internal;
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.Precompilation;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.Dnx.Compilation;
|
using Microsoft.Dnx.Compilation;
|
||||||
using Microsoft.Dnx.Compilation.CSharp;
|
using Microsoft.Dnx.Compilation.CSharp;
|
||||||
using Microsoft.Dnx.Runtime;
|
|
||||||
using Microsoft.Framework.Caching.Memory;
|
using Microsoft.Framework.Caching.Memory;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
|
|
@ -27,22 +27,22 @@ namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
||||||
{
|
{
|
||||||
public RazorPreCompiler(
|
public RazorPreCompiler(
|
||||||
[NotNull] BeforeCompileContext compileContext,
|
[NotNull] BeforeCompileContext compileContext,
|
||||||
[NotNull] IAssemblyLoadContext loadContext,
|
|
||||||
[NotNull] IFileProvider fileProvider,
|
[NotNull] IFileProvider fileProvider,
|
||||||
[NotNull] IMemoryCache precompilationCache)
|
[NotNull] IMemoryCache precompilationCache)
|
||||||
{
|
{
|
||||||
CompileContext = compileContext;
|
CompileContext = compileContext;
|
||||||
LoadContext = loadContext;
|
|
||||||
FileProvider = fileProvider;
|
FileProvider = fileProvider;
|
||||||
|
// There should always be a syntax tree even if there are no files (we generate one)
|
||||||
|
Debug.Assert(compileContext.Compilation.SyntaxTrees.Length > 0);
|
||||||
|
var defines = compileContext.Compilation.SyntaxTrees[0].Options.PreprocessorSymbolNames;
|
||||||
CompilationSettings = new CompilationSettings
|
CompilationSettings = new CompilationSettings
|
||||||
{
|
{
|
||||||
CompilationOptions = compileContext.Compilation.Options,
|
CompilationOptions = compileContext.Compilation.Options,
|
||||||
// REVIEW: There should always be a syntax tree even if there are no files (we generate one)
|
Defines = defines,
|
||||||
Defines = compileContext.Compilation.SyntaxTrees[0].Options.PreprocessorSymbolNames,
|
|
||||||
LanguageVersion = compileContext.Compilation.LanguageVersion
|
LanguageVersion = compileContext.Compilation.LanguageVersion
|
||||||
};
|
};
|
||||||
PreCompilationCache = precompilationCache;
|
PreCompilationCache = precompilationCache;
|
||||||
TagHelperTypeResolver = new PrecompilationTagHelperTypeResolver(CompileContext, LoadContext);
|
TagHelperTypeResolver = new PrecompilationTagHelperTypeResolver(CompileContext.Compilation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -54,8 +54,6 @@ namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
||||||
|
|
||||||
protected BeforeCompileContext CompileContext { get; }
|
protected BeforeCompileContext CompileContext { get; }
|
||||||
|
|
||||||
protected IAssemblyLoadContext LoadContext { get; }
|
|
||||||
|
|
||||||
protected CompilationSettings CompilationSettings { get; }
|
protected CompilationSettings CompilationSettings { get; }
|
||||||
|
|
||||||
protected IMemoryCache PreCompilationCache { get; }
|
protected IMemoryCache PreCompilationCache { get; }
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.Mvc.Razor.Host": "6.0.0-*",
|
"Microsoft.AspNet.Mvc.Razor.Host": "6.0.0-*",
|
||||||
"Microsoft.AspNet.Mvc.ViewFeatures": "6.0.0-*",
|
"Microsoft.AspNet.Mvc.ViewFeatures": "6.0.0-*",
|
||||||
|
"Microsoft.AspNet.Razor.Runtime.Precompilation": "4.0.0-*",
|
||||||
"Microsoft.AspNet.PageExecutionInstrumentation.Interfaces": "1.0.0-*",
|
"Microsoft.AspNet.PageExecutionInstrumentation.Interfaces": "1.0.0-*",
|
||||||
"Microsoft.Framework.HashCodeCombiner.Sources": { "version": "1.0.0-*", "type": "build" },
|
"Microsoft.Framework.HashCodeCombiner.Sources": { "version": "1.0.0-*", "type": "build" },
|
||||||
"Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" },
|
"Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" },
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ namespace PrecompilationWebSite
|
||||||
{
|
{
|
||||||
public class RazorPreCompilation : RazorPreCompileModule
|
public class RazorPreCompilation : RazorPreCompileModule
|
||||||
{
|
{
|
||||||
public RazorPreCompilation(IServiceProvider provider)
|
public RazorPreCompilation()
|
||||||
: base(provider)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue