Modify ICompilationLibrariesProvider to return a sequence of reference path

Fixes #4738
This commit is contained in:
Pranav K 2016-05-24 17:39:27 -07:00
parent 9acd0f578c
commit 5d72a7f747
5 changed files with 51 additions and 38 deletions

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.Extensions.DependencyModel; using Microsoft.Extensions.DependencyModel;
@ -11,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationParts
/// <summary> /// <summary>
/// An <see cref="ApplicationPart"/> backed by an <see cref="Assembly"/>. /// An <see cref="ApplicationPart"/> backed by an <see cref="Assembly"/>.
/// </summary> /// </summary>
public class AssemblyPart : ApplicationPart, IApplicationPartTypeProvider, ICompilationLibrariesProvider public class AssemblyPart : ApplicationPart, IApplicationPartTypeProvider, ICompilationReferencesProvider
{ {
/// <summary> /// <summary>
/// Initalizes a new <see cref="AssemblyPart"/> instance. /// Initalizes a new <see cref="AssemblyPart"/> instance.
@ -41,15 +42,19 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationParts
public IEnumerable<TypeInfo> Types => Assembly.DefinedTypes; public IEnumerable<TypeInfo> Types => Assembly.DefinedTypes;
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyList<CompilationLibrary> GetCompilationLibraries() public IEnumerable<string> GetReferencePaths()
{ {
var dependencyContext = DependencyContext.Load(Assembly); var dependencyContext = DependencyContext.Load(Assembly);
if (dependencyContext != null) if (dependencyContext != null)
{ {
return dependencyContext.CompileLibraries; return dependencyContext.CompileLibraries.SelectMany(library => library.ResolveReferencePaths());
} }
return new CompilationLibrary[0]; // If an application has been compiled without preserveCompilationContext, return the path to the assembly
// as a reference. For runtime compilation, this will allow the compilation to succeed as long as it least
// one application part has been compiled with preserveCompilationContext and contains a super set of types
// required for the compilation to succeed.
return new[] { Assembly.Location };
} }
} }
} }

View File

@ -2,18 +2,17 @@
// 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.Collections.Generic; using System.Collections.Generic;
using Microsoft.Extensions.DependencyModel;
namespace Microsoft.AspNetCore.Mvc.ApplicationParts namespace Microsoft.AspNetCore.Mvc.ApplicationParts
{ {
/// <summary> /// <summary>
/// Exposes <see cref="CompilationLibrary"/> instances from an <see cref="ApplicationPart"/>. /// Exposes one or more reference paths from an <see cref="ApplicationPart"/>.
/// </summary> /// </summary>
public interface ICompilationLibrariesProvider public interface ICompilationReferencesProvider
{ {
/// <summary> /// <summary>
/// Gets the sequence of <see cref="CompilationLibrary"/> instances. /// Gets reference paths used to perform runtime compilation.
/// </summary> /// </summary>
IReadOnlyList<CompilationLibrary> GetCompilationLibraries(); IEnumerable<string> GetReferencePaths();
} }
} }

View File

@ -33,21 +33,15 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
} }
var libraryPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var libraryPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var providerPart in parts.OfType<ICompilationLibrariesProvider>()) foreach (var providerPart in parts.OfType<ICompilationReferencesProvider>())
{ {
var compileLibraries = providerPart.GetCompilationLibraries(); var referencePaths = providerPart.GetReferencePaths();
foreach (var path in referencePaths)
for (var i = 0; i < compileLibraries.Count; i++)
{ {
var library = compileLibraries[i]; if (libraryPaths.Add(path))
var referencePaths = library.ResolveReferencePaths();
foreach (var path in referencePaths)
{ {
if (libraryPaths.Add(path)) var metadataReference = CreateMetadataReference(path);
{ feature.MetadataReferences.Add(metadataReference);
var metadataReference = CreateMetadataReference(path);
feature.MetadataReferences.Add(metadataReference);
}
} }
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Reflection; using System.Reflection;
using Xunit; using Xunit;
@ -46,5 +47,36 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationParts
// Act & Assert // Act & Assert
Assert.Equal(part.Assembly, assembly); Assert.Equal(part.Assembly, assembly);
} }
[Fact]
public void GetReferencePaths_ReturnsReferencesFromDependencyContext_IfPreserveCompilationContextIsSet()
{
// Arrange
var assembly = GetType().GetTypeInfo().Assembly;
var part = new AssemblyPart(assembly);
// Act
var references = part.GetReferencePaths().ToList();
// Assert
Assert.Contains(assembly.Location, references);
Assert.Contains(typeof(AssemblyPart).GetTypeInfo().Assembly.Location, references);
}
[Fact]
public void GetReferencePaths_ReturnsAssebmlyLocation_IfPreserveCompilationContextIsNotSet()
{
// Arrange
// src projects do not have preserveCompilationContext specified.
var assembly = typeof(AssemblyPart).GetTypeInfo().Assembly;
var part = new AssemblyPart(assembly);
// Act
var references = part.GetReferencePaths().ToList();
// Assert
var actual = Assert.Single(references);
Assert.Equal(assembly.Location, actual);
}
} }
} }

View File

@ -26,23 +26,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
Assert.Empty(feature.MetadataReferences); Assert.Empty(feature.MetadataReferences);
} }
[Fact]
public void PopulateFeature_ReturnsEmptySequence_IfAssemblyDoesNotPreserveCompilationContext()
{
// Arrange
var applicationPartManager = new ApplicationPartManager();
var assemblyPart = new AssemblyPart(typeof(MetadataReferenceFeatureProvider).GetTypeInfo().Assembly);
applicationPartManager.ApplicationParts.Add(assemblyPart);
applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
var feature = new MetadataReferenceFeature();
// Act
applicationPartManager.PopulateFeature(feature);
// Assert
Assert.Empty(feature.MetadataReferences);
}
[Fact] [Fact]
public void PopulateFeature_AddsMetadataReferenceForAssemblyPartsWithDependencyContext() public void PopulateFeature_AddsMetadataReferenceForAssemblyPartsWithDependencyContext()
{ {