aspnetcore/test/Microsoft.AspNet.Razor.Runt.../CompilationUtility.cs

84 lines
3.4 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.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Dnx.Compilation.CSharp;
using Microsoft.Extensions.CompilationAbstractions;
using Microsoft.Extensions.PlatformAbstractions;
namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{
public static class CompilationUtility
{
private static readonly ConcurrentDictionary<string, AssemblyMetadata> _metadataCache =
new ConcurrentDictionary<string, AssemblyMetadata>(StringComparer.Ordinal);
private static readonly Assembly ExecutingAssembly = typeof(CompilationUtility).GetTypeInfo().Assembly;
public static readonly string GeneratedAssemblyName = Path.GetRandomFileName() + "." + Path.GetRandomFileName();
public static CodeAnalysis.Compilation GetCompilation(params string[] resourceFiles)
{
var assemblyVersion = ExecutingAssembly.GetName().Version;
var syntaxTrees = new List<SyntaxTree>
{
CSharpSyntaxTree.ParseText(
$"[assembly: {typeof(AssemblyVersionAttribute).FullName}(\"{assemblyVersion}\")]")
};
foreach (var resourceFile in resourceFiles)
{
var resourceContent = ReadManifestResource(resourceFile);
syntaxTrees.Add(CSharpSyntaxTree.ParseText(resourceContent));
}
var libraryExporter = CompilationServices.Default.LibraryExporter;
var applicationName = ExecutingAssembly.GetName().Name;
var libraryExport = libraryExporter.GetExport(applicationName);
var references = new List<MetadataReference>();
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);
}
else
{
var export = libraryExporter.GetAllExports(applicationName);
foreach (var metadataReference in export.MetadataReferences)
{
var reference = metadataReference.ConvertMetadataReference(
fileReference => _metadataCache.GetOrAdd(
fileReference.Path,
_ => fileReference.CreateAssemblyMetadata()));
references.Add(reference);
}
}
return CSharpCompilation.Create(
GeneratedAssemblyName,
syntaxTrees,
references);
}
private static string ReadManifestResource(string path)
{
path = $"{ExecutingAssembly.GetName().Name}.{path}.cs";
using (var contentStream = ExecutingAssembly.GetManifestResourceStream(path))
{
using (var reader = new StreamReader(contentStream))
{
return reader.ReadToEnd();
}
}
}
}
}