Simplify assembly load on CoreCLR

Fixes #4328
This commit is contained in:
Pranav K 2016-04-22 00:11:31 -07:00
parent 756cd2dab8
commit b3a65b485f
2 changed files with 33 additions and 48 deletions

View File

@ -2,17 +2,14 @@
// 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; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
#if NETSTANDARD1_5
using System.Runtime.Loader;
#endif
using System.Text; using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Razor.Compilation; using Microsoft.AspNetCore.Mvc.Razor.Compilation;
@ -32,19 +29,15 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
/// </summary> /// </summary>
public class DefaultRoslynCompilationService : ICompilationService public class DefaultRoslynCompilationService : ICompilationService
{ {
private readonly ConcurrentDictionary<string, AssemblyMetadata> _metadataFileCache =
new ConcurrentDictionary<string, AssemblyMetadata>(StringComparer.OrdinalIgnoreCase);
private readonly IFileProvider _fileProvider; private readonly IFileProvider _fileProvider;
private readonly Lazy<List<MetadataReference>> _applicationReferences;
private readonly Action<RoslynCompilationContext> _compilationCallback; private readonly Action<RoslynCompilationContext> _compilationCallback;
private readonly CSharpParseOptions _parseOptions; private readonly CSharpParseOptions _parseOptions;
private readonly CSharpCompilationOptions _compilationOptions; private readonly CSharpCompilationOptions _compilationOptions;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly DependencyContext _dependencyContext; private readonly DependencyContext _dependencyContext;
private object _applicationReferencesLock = new object();
#if NETSTANDARD1_5 private bool _applicationReferencesInitialized;
private readonly RazorLoadContext _razorLoadContext; private List<MetadataReference> _applicationReferences;
#endif
/// <summary> /// <summary>
/// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class. /// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class.
@ -74,16 +67,23 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory)
{ {
_dependencyContext = dependencyContext; _dependencyContext = dependencyContext;
_applicationReferences = new Lazy<List<MetadataReference>>(GetApplicationReferences);
_fileProvider = fileProviderAccessor.FileProvider; _fileProvider = fileProviderAccessor.FileProvider;
_compilationCallback = viewEngineOptions.CompilationCallback; _compilationCallback = viewEngineOptions.CompilationCallback;
_parseOptions = viewEngineOptions.ParseOptions; _parseOptions = viewEngineOptions.ParseOptions;
_compilationOptions = viewEngineOptions.CompilationOptions; _compilationOptions = viewEngineOptions.CompilationOptions;
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>(); _logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
}
#if NETSTANDARD1_5 private List<MetadataReference> ApplicationReferences
_razorLoadContext = new RazorLoadContext(); {
#endif get
{
return LazyInitializer.EnsureInitialized(
ref _applicationReferences,
ref _applicationReferencesInitialized,
ref _applicationReferencesLock,
GetApplicationReferences);
}
} }
/// <inheritdoc /> /// <inheritdoc />
@ -115,7 +115,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
assemblyName, assemblyName,
options: _compilationOptions, options: _compilationOptions,
syntaxTrees: new[] { syntaxTree }, syntaxTrees: new[] { syntaxTree },
references: _applicationReferences.Value); references: ApplicationReferences);
compilation = Rewrite(compilation); compilation = Rewrite(compilation);
@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
if (!result.Success) if (!result.Success)
{ {
if (!compilation.References.Any() && !_applicationReferences.Value.Any()) if (!compilation.References.Any() && !ApplicationReferences.Any())
{ {
// DependencyModel had no references specified and the user did not use the // 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 // CompilationCallback to add extra references. It is likely that the user did not specify
@ -165,12 +165,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
} }
} }
private Assembly LoadStream(MemoryStream ms, MemoryStream assemblySymbols) private Assembly LoadStream(MemoryStream assemblyStream, MemoryStream pdbStream)
{ {
#if NET451 #if NET451
return Assembly.Load(ms.ToArray(), assemblySymbols.ToArray()); return Assembly.Load(assemblyStream.ToArray(), pdbStream.ToArray());
#else #else
return _razorLoadContext.Load(ms, assemblySymbols); return System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(assemblyStream, pdbStream);
#endif #endif
} }
@ -247,6 +247,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
return metadataReferences; return metadataReferences;
} }
var libraryPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
for (var i = 0; i < _dependencyContext.CompileLibraries.Count; i++) for (var i = 0; i < _dependencyContext.CompileLibraries.Count; i++)
{ {
var library = _dependencyContext.CompileLibraries[i]; var library = _dependencyContext.CompileLibraries[i];
@ -260,7 +261,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
continue; continue;
} }
metadataReferences.AddRange(referencePaths.Select(CreateMetadataFileReference)); foreach (var path in referencePaths)
{
if (libraryPaths.Add(path))
{
metadataReferences.Add(CreateMetadataFileReference(path));
}
}
} }
return metadataReferences; return metadataReferences;
@ -268,16 +275,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
private MetadataReference CreateMetadataFileReference(string path) private MetadataReference CreateMetadataFileReference(string path)
{ {
var metadata = _metadataFileCache.GetOrAdd(path, _ => using (var stream = File.OpenRead(path))
{ {
using (var stream = File.OpenRead(path)) var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
{ var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);
var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
return AssemblyMetadata.Create(moduleMetadata);
}
});
return metadata.GetReference(filePath: path); return assemblyMetadata.GetReference(filePath: path);
}
} }
private static bool IsError(Diagnostic diagnostic) private static bool IsError(Diagnostic diagnostic)
@ -329,20 +333,5 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
return null; return null;
} }
#if NETSTANDARD1_5
private class RazorLoadContext : AssemblyLoadContext
{
protected override Assembly Load(AssemblyName assemblyName)
{
return Default.LoadFromAssemblyName(assemblyName);
}
public Assembly Load(Stream assembly, Stream assemblySymbols)
{
return LoadFromStream(assembly, assemblySymbols);
}
}
#endif
} }
} }

View File

@ -40,9 +40,6 @@
"frameworks": { "frameworks": {
"net451": { "net451": {
"frameworkAssemblies": { "frameworkAssemblies": {
"System.Threading.Tasks": {
"type": "build"
}
} }
}, },
"netstandard1.5": { "netstandard1.5": {
@ -51,7 +48,6 @@
], ],
"dependencies": { "dependencies": {
"System.Text.Encoding": "4.0.11-*", "System.Text.Encoding": "4.0.11-*",
"System.Threading.Tasks.Parallel": "4.0.1-*",
"System.Runtime.Loader": "4.0.0-*" "System.Runtime.Loader": "4.0.0-*"
} }
} }