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 CSharpParseOptions _parseOptions;
|
||||
private readonly CSharpCompilationOptions _compilationOptions;
|
||||
private readonly IList<MetadataReference> _additionalMetadataReferences;
|
||||
private readonly ILogger _logger;
|
||||
private object _applicationReferencesLock = new object();
|
||||
private bool _applicationReferencesInitialized;
|
||||
private IList<MetadataReference> _applicationReferences;
|
||||
private object _compilationReferencesLock = new object();
|
||||
private bool _compilationReferencesInitialized;
|
||||
private IList<MetadataReference> _compilationReferences;
|
||||
|
||||
/// <summary>
|
||||
/// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class.
|
||||
|
|
@ -55,18 +56,19 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
_compilationCallback = optionsAccessor.Value.CompilationCallback;
|
||||
_parseOptions = optionsAccessor.Value.ParseOptions;
|
||||
_compilationOptions = optionsAccessor.Value.CompilationOptions;
|
||||
_additionalMetadataReferences = optionsAccessor.Value.AdditionalCompilationReferences;
|
||||
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
|
||||
}
|
||||
|
||||
private IList<MetadataReference> ApplicationReferences
|
||||
private IList<MetadataReference> CompilationReferences
|
||||
{
|
||||
get
|
||||
{
|
||||
return LazyInitializer.EnsureInitialized(
|
||||
ref _applicationReferences,
|
||||
ref _applicationReferencesInitialized,
|
||||
ref _applicationReferencesLock,
|
||||
GetApplicationReferences);
|
||||
ref _compilationReferences,
|
||||
ref _compilationReferencesInitialized,
|
||||
ref _compilationReferencesLock,
|
||||
GetCompilationReferences);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +101,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
assemblyName,
|
||||
options: _compilationOptions,
|
||||
syntaxTrees: new[] { syntaxTree },
|
||||
references: ApplicationReferences);
|
||||
references: CompilationReferences);
|
||||
|
||||
compilation = Rewrite(compilation);
|
||||
|
||||
|
|
@ -118,7 +120,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
|
||||
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
|
||||
// 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.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="MetadataReference"/> instances.</returns>
|
||||
protected virtual IList<MetadataReference> GetApplicationReferences()
|
||||
protected virtual IList<MetadataReference> GetCompilationReferences()
|
||||
{
|
||||
var feature = new MetadataReferenceFeature();
|
||||
_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)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
|
||||
|
|
@ -90,6 +91,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
/// </remarks>
|
||||
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>
|
||||
/// Gets or sets the callback that is used to customize Razor compilation
|
||||
/// 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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
|
|
@ -316,6 +318,34 @@ public class MyNonCustomDefinedClass {}
|
|||
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)
|
||||
{
|
||||
return new DiagnosticDescriptor(
|
||||
|
|
@ -375,5 +405,15 @@ public class MyNonCustomDefinedClass {}
|
|||
GetFileProviderAccessor(fileProvider),
|
||||
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