// 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 { /// /// A type that uses Roslyn to compile C# content and to find out references. /// public class DefaultRoslynCompilationService : RoslynCompilationService { private readonly IApplicationEnvironment _environment; private readonly ILibraryExporter _libraryExporter; /// /// Initalizes a new instance of the class. /// /// The environment for the executing application. /// The library manager that provides export and reference information. /// The that was used to generate the code. /// Accessor to . /// The . /// The . public DefaultRoslynCompilationService(IApplicationEnvironment environment, ILibraryExporter libraryExporter, IMvcRazorHost host, IOptions optionsAccessor, IRazorViewEngineFileProviderAccessor fileProviderAccessor, ILoggerFactory loggerFactory) : base(environment, host, optionsAccessor, fileProviderAccessor, loggerFactory) { _environment = environment; _libraryExporter = libraryExporter; } protected override List GetApplicationReferences() { var references = new List(); // 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(); } } }