aspnetcore/src/Microsoft.AspNet.Mvc.Razor/Compilation/DefaultRoslynCompilationSer...

121 lines
5.5 KiB
C#

// 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.Diagnostics;
using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.Dnx.Compilation.CSharp;
using Microsoft.Extensions.CompilationAbstractions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.PlatformAbstractions;
namespace Microsoft.AspNet.Mvc.Razor.Compilation
{
/// <summary>
/// A type that uses Roslyn to compile C# content and <see cref="ILibraryExporter"/> to find out references.
/// </summary>
public class DefaultRoslynCompilationService : RoslynCompilationService
{
private readonly IApplicationEnvironment _environment;
private readonly ILibraryExporter _libraryExporter;
/// <summary>
/// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class.
/// </summary>
/// <param name="environment">The environment for the executing application.</param>
/// <param name="libraryExporter">The library manager that provides export and reference information.</param>
/// <param name="host">The <see cref="IMvcRazorHost"/> that was used to generate the code.</param>
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
public DefaultRoslynCompilationService(IApplicationEnvironment environment,
ILibraryExporter libraryExporter,
IMvcRazorHost host,
IOptions<RazorViewEngineOptions> optionsAccessor,
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
ILoggerFactory loggerFactory)
: base(environment, host, optionsAccessor, fileProviderAccessor, loggerFactory)
{
_environment = environment;
_libraryExporter = libraryExporter;
}
protected override List<MetadataReference> GetApplicationReferences()
{
var references = new List<MetadataReference>();
// Get the MetadataReference for the executing application. If it's a Roslyn reference,
// we can copy the references created when compiling the application to the Razor page being compiled.
// This avoids performing expensive calls to MetadataReference.CreateFromImage.
var libraryExport = _libraryExporter.GetExport(_environment.ApplicationName);
if (libraryExport?.MetadataReferences != null && libraryExport.MetadataReferences.Count > 0)
{
Debug.Assert(libraryExport.MetadataReferences.Count == 1,
"Expected 1 MetadataReferences, found " + libraryExport.MetadataReferences.Count);
var roslynReference = libraryExport.MetadataReferences[0] as IRoslynMetadataReference;
var compilationReference = roslynReference?.MetadataReference as CompilationReference;
if (compilationReference != null)
{
references.AddRange(compilationReference.Compilation.References);
references.Add(roslynReference.MetadataReference);
return references;
}
}
var export = _libraryExporter.GetAllExports(_environment.ApplicationName);
if (export != null)
{
foreach (var metadataReference in export.MetadataReferences)
{
// Taken from https://github.com/aspnet/KRuntime/blob/757ba9bfdf80bd6277e715d6375969a7f44370ee/src/...
// Microsoft.Extensions.Runtime.Roslyn/RoslynCompiler.cs#L164
// We don't want to take a dependency on the Roslyn bit directly since it pulls in more dependencies
// than the view engine needs (Microsoft.Extensions.Runtime) for example
references.Add(ConvertMetadataReference(metadataReference));
}
}
return references;
}
private MetadataReference ConvertMetadataReference(IMetadataReference metadataReference)
{
var roslynReference = metadataReference as IRoslynMetadataReference;
if (roslynReference != null)
{
return roslynReference.MetadataReference;
}
var embeddedReference = metadataReference as IMetadataEmbeddedReference;
if (embeddedReference != null)
{
return MetadataReference.CreateFromImage(embeddedReference.Contents);
}
var fileMetadataReference = metadataReference as IMetadataFileReference;
if (fileMetadataReference != null)
{
return CreateMetadataFileReference(fileMetadataReference.Path);
}
var projectReference = metadataReference as IMetadataProjectReference;
if (projectReference != null)
{
using (var ms = new MemoryStream())
{
projectReference.EmitReferenceAssembly(ms);
return MetadataReference.CreateFromImage(ms.ToArray());
}
}
throw new NotSupportedException();
}
}
}