Add `AdditionalCompilationReferences` option to `RazorViewEngineOptions`.
- `AdditionalCompilationReferences` is a purely additive option to add `MetadataReference` instances to be used for Razor compilation. - Added a test to validate the compilation references get combined with the `ApplicationPartManager`s metadata references. #4497
This commit is contained in:
parent
659cdc3364
commit
51c285574b
|
|
@ -32,10 +32,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
private readonly Action<RoslynCompilationContext> _compilationCallback;
|
private readonly Action<RoslynCompilationContext> _compilationCallback;
|
||||||
private readonly CSharpParseOptions _parseOptions;
|
private readonly CSharpParseOptions _parseOptions;
|
||||||
private readonly CSharpCompilationOptions _compilationOptions;
|
private readonly CSharpCompilationOptions _compilationOptions;
|
||||||
|
private readonly IList<MetadataReference> _additionalMetadataReferences;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private object _applicationReferencesLock = new object();
|
private object _compilationReferencesLock = new object();
|
||||||
private bool _applicationReferencesInitialized;
|
private bool _compilationReferencesInitialized;
|
||||||
private IList<MetadataReference> _applicationReferences;
|
private IList<MetadataReference> _compilationReferences;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class.
|
/// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class.
|
||||||
|
|
@ -55,18 +56,19 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
_compilationCallback = optionsAccessor.Value.CompilationCallback;
|
_compilationCallback = optionsAccessor.Value.CompilationCallback;
|
||||||
_parseOptions = optionsAccessor.Value.ParseOptions;
|
_parseOptions = optionsAccessor.Value.ParseOptions;
|
||||||
_compilationOptions = optionsAccessor.Value.CompilationOptions;
|
_compilationOptions = optionsAccessor.Value.CompilationOptions;
|
||||||
|
_additionalMetadataReferences = optionsAccessor.Value.AdditionalCompilationReferences;
|
||||||
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
|
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IList<MetadataReference> ApplicationReferences
|
private IList<MetadataReference> CompilationReferences
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return LazyInitializer.EnsureInitialized(
|
return LazyInitializer.EnsureInitialized(
|
||||||
ref _applicationReferences,
|
ref _compilationReferences,
|
||||||
ref _applicationReferencesInitialized,
|
ref _compilationReferencesInitialized,
|
||||||
ref _applicationReferencesLock,
|
ref _compilationReferencesLock,
|
||||||
GetApplicationReferences);
|
GetCompilationReferences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,7 +101,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
assemblyName,
|
assemblyName,
|
||||||
options: _compilationOptions,
|
options: _compilationOptions,
|
||||||
syntaxTrees: new[] { syntaxTree },
|
syntaxTrees: new[] { syntaxTree },
|
||||||
references: ApplicationReferences);
|
references: CompilationReferences);
|
||||||
|
|
||||||
compilation = Rewrite(compilation);
|
compilation = Rewrite(compilation);
|
||||||
|
|
||||||
|
|
@ -118,7 +120,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
|
|
||||||
if (!result.Success)
|
if (!result.Success)
|
||||||
{
|
{
|
||||||
if (!compilation.References.Any() && !ApplicationReferences.Any())
|
if (!compilation.References.Any() && !CompilationReferences.Any())
|
||||||
{
|
{
|
||||||
// DependencyModel had no references specified and the user did not use the
|
// DependencyModel had no references specified and the user did not use the
|
||||||
// CompilationCallback to add extra references. It is likely that the user did not specify
|
// CompilationCallback to add extra references. It is likely that the user did not specify
|
||||||
|
|
@ -153,11 +155,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
/// Gets the sequence of <see cref="MetadataReference"/> instances used for compilation.
|
/// Gets the sequence of <see cref="MetadataReference"/> instances used for compilation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The <see cref="MetadataReference"/> instances.</returns>
|
/// <returns>The <see cref="MetadataReference"/> instances.</returns>
|
||||||
protected virtual IList<MetadataReference> GetApplicationReferences()
|
protected virtual IList<MetadataReference> GetCompilationReferences()
|
||||||
{
|
{
|
||||||
var feature = new MetadataReferenceFeature();
|
var feature = new MetadataReferenceFeature();
|
||||||
_partManager.PopulateFeature(feature);
|
_partManager.PopulateFeature(feature);
|
||||||
return feature.MetadataReferences;
|
var applicationReferences = feature.MetadataReferences;
|
||||||
|
|
||||||
|
if (_additionalMetadataReferences.Count == 0)
|
||||||
|
{
|
||||||
|
return applicationReferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
var compilationReferences = new List<MetadataReference>(applicationReferences.Count + _additionalMetadataReferences.Count);
|
||||||
|
compilationReferences.AddRange(applicationReferences);
|
||||||
|
compilationReferences.AddRange(_additionalMetadataReferences);
|
||||||
|
|
||||||
|
return compilationReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Assembly LoadStream(MemoryStream assemblyStream, MemoryStream pdbStream)
|
private Assembly LoadStream(MemoryStream assemblyStream, MemoryStream pdbStream)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
||||||
|
|
@ -90,6 +91,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public IList<string> AreaViewLocationFormats { get; } = new List<string>();
|
public IList<string> AreaViewLocationFormats { get; } = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="MetadataReference" /> instances that should be included in Razor compilation, along with
|
||||||
|
/// those discovered by <see cref="MetadataReferenceFeatureProvider" />s.
|
||||||
|
/// </summary>
|
||||||
|
public IList<MetadataReference> AdditionalCompilationReferences { get; } = new List<MetadataReference>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the callback that is used to customize Razor compilation
|
/// Gets or sets the callback that is used to customize Razor compilation
|
||||||
/// to change compilation settings you can update <see cref="RoslynCompilationContext.Compilation"/> property.
|
/// to change compilation settings you can update <see cref="RoslynCompilationContext.Compilation"/> property.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||||
|
|
@ -316,6 +318,34 @@ public class MyNonCustomDefinedClass {}
|
||||||
Assert.NotNull(result.CompiledType);
|
Assert.NotNull(result.CompiledType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetCompilationReferences_CombinesApplicationPartAndOptionMetadataReferences()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var options = new RazorViewEngineOptions();
|
||||||
|
var objectAssemblyLocation = typeof(object).GetTypeInfo().Assembly.Location;
|
||||||
|
var objectAssemblyMetadataReference = MetadataReference.CreateFromFile(objectAssemblyLocation);
|
||||||
|
options.AdditionalCompilationReferences.Add(objectAssemblyMetadataReference);
|
||||||
|
var applicationPartManager = GetApplicationPartManager();
|
||||||
|
var compilationService = new TestRoslynCompilationService(applicationPartManager, options);
|
||||||
|
var feature = new MetadataReferenceFeature();
|
||||||
|
applicationPartManager.PopulateFeature(feature);
|
||||||
|
var partReferences = feature.MetadataReferences;
|
||||||
|
var expectedReferences = new List<MetadataReference>();
|
||||||
|
expectedReferences.AddRange(partReferences);
|
||||||
|
expectedReferences.Add(objectAssemblyMetadataReference);
|
||||||
|
var expectedReferenceDisplays = expectedReferences.Select(reference => reference.Display);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var references = compilationService.GetCompilationReferencesPublic();
|
||||||
|
var referenceDisplays = references.Select(reference => reference.Display);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(references);
|
||||||
|
Assert.NotEmpty(references);
|
||||||
|
Assert.Equal(expectedReferenceDisplays, referenceDisplays);
|
||||||
|
}
|
||||||
|
|
||||||
private static DiagnosticDescriptor GetDiagnosticDescriptor(string messageFormat)
|
private static DiagnosticDescriptor GetDiagnosticDescriptor(string messageFormat)
|
||||||
{
|
{
|
||||||
return new DiagnosticDescriptor(
|
return new DiagnosticDescriptor(
|
||||||
|
|
@ -375,5 +405,15 @@ public class MyNonCustomDefinedClass {}
|
||||||
GetFileProviderAccessor(fileProvider),
|
GetFileProviderAccessor(fileProvider),
|
||||||
NullLoggerFactory.Instance);
|
NullLoggerFactory.Instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestRoslynCompilationService : DefaultRoslynCompilationService
|
||||||
|
{
|
||||||
|
public TestRoslynCompilationService(ApplicationPartManager partManager, RazorViewEngineOptions options)
|
||||||
|
: base(partManager, GetAccessor(options), GetFileProviderAccessor(), NullLoggerFactory.Instance)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<MetadataReference> GetCompilationReferencesPublic() => GetCompilationReferences();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue