提交 f216102e 编写于 作者: T Tomas Matousek

Avoid accessing GAC when not available (on CoreCLR)

上级 df852712
...@@ -76,7 +76,7 @@ private static class _Assembly ...@@ -76,7 +76,7 @@ private static class _Assembly
private static class _ResolveEventArgs private static class _ResolveEventArgs
{ {
internal static readonly Type Type = Type.GetType("System.ResolveEventArgs", throwOnError: false); internal static readonly Type Type = ReflectionUtilities.TryGetType("System.ResolveEventArgs");
internal static readonly MethodInfo get_Name = Type internal static readonly MethodInfo get_Name = Type
.GetTypeInfo() .GetTypeInfo()
...@@ -89,8 +89,8 @@ private static class _ResolveEventArgs ...@@ -89,8 +89,8 @@ private static class _ResolveEventArgs
private static class _AppDomain private static class _AppDomain
{ {
internal static readonly Type Type = Type.GetType("System.AppDomain", throwOnError: false); internal static readonly Type Type = ReflectionUtilities.TryGetType("System.AppDomain");
internal static readonly Type ResolveEventHandlerType = Type.GetType("System.ResolveEventHandler", throwOnError: false); internal static readonly Type ResolveEventHandlerType = ReflectionUtilities.TryGetType("System.ResolveEventHandler");
internal static readonly MethodInfo get_CurrentDomain = Type internal static readonly MethodInfo get_CurrentDomain = Type
.GetTypeInfo() .GetTypeInfo()
......
...@@ -10,17 +10,30 @@ namespace Roslyn.Utilities ...@@ -10,17 +10,30 @@ namespace Roslyn.Utilities
{ {
internal static class ReflectionUtilities internal static class ReflectionUtilities
{ {
public static Type TryGetType(string assemblyQualifiedName)
{
try
{
// Note that throwOnError=false only suppresses some exceptions, not all.
return Type.GetType(assemblyQualifiedName, throwOnError: false);
}
catch
{
return null;
}
}
/// <summary> /// <summary>
/// Find a <see cref="Type"/> instance by first probing the contract name and then the name as it /// Find a <see cref="Type"/> instance by first probing the contract name and then the name as it
/// would exist in mscorlib. This helps satisfy both the CoreCLR and Desktop scenarios. /// would exist in mscorlib. This helps satisfy both the CoreCLR and Desktop scenarios.
/// </summary> /// </summary>
public static Type GetTypeFromEither(string contractName, string desktopName) public static Type GetTypeFromEither(string contractName, string desktopName)
{ {
var type = Type.GetType(contractName, throwOnError: false); var type = TryGetType(contractName);
if (type == null) if (type == null)
{ {
type = Type.GetType(desktopName, throwOnError: false); type = TryGetType(desktopName);
} }
return type; return type;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
namespace Roslyn.Utilities namespace Roslyn.Utilities
{ {
/// <summary> /// <summary>
/// This is a bridge for APIs that are only available on CoreCLR or .NET 4.6 /// This is a bridge for APIs that are only available on CoreCLR or .NET 4.6
/// and NOT on .NET 4.5. The compiler currently targets .NET 4.5 and CoreCLR /// and NOT on .NET 4.5. The compiler currently targets .NET 4.5 and CoreCLR
...@@ -14,13 +13,20 @@ namespace Roslyn.Utilities ...@@ -14,13 +13,20 @@ namespace Roslyn.Utilities
/// </summary> /// </summary>
internal static class CoreClrShim internal static class CoreClrShim
{ {
internal static class AssemblyLoadContext
{
internal static readonly Type Type = ReflectionUtilities.TryGetType(
"System.Runtime.Loader.AssemblyLoadContext, System.Runtime.Loader, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
}
internal static class CodePagesEncodingProvider internal static class CodePagesEncodingProvider
{ {
internal static readonly Type Type = internal static readonly Type Type = ReflectionUtilities.TryGetType(
Type.GetType("System.Text.CodePagesEncodingProvider, " + "System.Text.CodePagesEncodingProvider, " +
"System.Text.Encoding.CodePages, " + "System.Text.Encoding.CodePages, " +
"Version=4.0.0.0, Culture=neutral, " + "Version=4.0.0.0, Culture=neutral, " +
"PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false); "PublicKeyToken=b03f5f7f11d50a3a");
private static PropertyInfo s_instance = Type private static PropertyInfo s_instance = Type
?.GetTypeInfo() ?.GetTypeInfo()
......
...@@ -11,37 +11,46 @@ ...@@ -11,37 +11,46 @@
namespace Microsoft.CodeAnalysis.Scripting.Hosting namespace Microsoft.CodeAnalysis.Scripting.Hosting
{ {
/// <summary> /// <summary>
/// Extends MetadataFileReferenceResolver to enable resolution of assembly /// Resolves assembly identities in Global Assembly Cache.
/// simple names in the GAC.
/// </summary> /// </summary>
internal sealed class GacFileResolver : IEquatable<GacFileResolver> internal sealed class GacFileResolver : IEquatable<GacFileResolver>
{ {
/// <summary> /// <summary>
/// Architecture filter used when resolving assembly references. /// Returns true if GAC is available on the platform.
/// </summary> /// </summary>
public ImmutableArray<ProcessorArchitecture> Architectures { get; } public static bool IsAvailable => CoreClrShim.AssemblyLoadContext.Type == null;
/// <summary> /// <summary>
/// CultureInfo used when resolving assembly references. /// Architecture filter used when resolving assembly references.
/// </summary> /// </summary>
public CultureInfo PreferredCulture { get; } public ImmutableArray<ProcessorArchitecture> Architectures { get; }
/// <summary> /// <summary>
/// A resolver that is configured to resolve against the GAC associated /// <see cref="CultureInfo"/> used when resolving assembly references, or null to prefer no culture.
/// with the bitness of the currently executing process.
/// </summary> /// </summary>
internal static GacFileResolver Default = new GacFileResolver( public CultureInfo PreferredCulture { get; }
architectures: GlobalAssemblyCache.CurrentArchitectures,
preferredCulture: null);
/// <summary> /// <summary>
/// Constructs an instance of a <see cref="GacFileResolver"/> /// Creates an instance of a <see cref="GacFileResolver"/>, if available on the platform (check <see cref="IsAvailable"/>).
/// </summary> /// </summary>
/// <param name="architectures">Supported architectures used to filter GAC assemblies.</param> /// <param name="architectures">Supported architectures used to filter GAC assemblies.</param>
/// <param name="preferredCulture">A culture to use when choosing the best assembly from /// <param name="preferredCulture">A culture to use when choosing the best assembly from
/// among the set filtered by <paramref name="architectures"/></param> /// among the set filtered by <paramref name="architectures"/></param>
public GacFileResolver(ImmutableArray<ProcessorArchitecture> architectures, CultureInfo preferredCulture) /// <exception cref="PlatformNotSupportedException">The platform doesn't support GAC.</exception>
public GacFileResolver(
ImmutableArray<ProcessorArchitecture> architectures = default(ImmutableArray<ProcessorArchitecture>),
CultureInfo preferredCulture = null)
{ {
if (!IsAvailable)
{
throw new PlatformNotSupportedException();
}
if (architectures.IsDefault)
{
architectures = GlobalAssemblyCache.CurrentArchitectures;
}
Architectures = architectures; Architectures = architectures;
PreferredCulture = preferredCulture; PreferredCulture = preferredCulture;
} }
......
...@@ -87,13 +87,19 @@ private enum ASM_CACHE ...@@ -87,13 +87,19 @@ private enum ASM_CACHE
private const int ERROR_INSUFFICIENT_BUFFER = unchecked((int)0x8007007A); private const int ERROR_INSUFFICIENT_BUFFER = unchecked((int)0x8007007A);
public static readonly ImmutableArray<string> RootLocations; public static ImmutableArray<string> s_rootLocations;
static GlobalAssemblyCache() public static ImmutableArray<string> RootLocations
{ {
RootLocations = ImmutableArray.Create<string>( get
GetLocation(ASM_CACHE.ROOT), {
GetLocation(ASM_CACHE.ROOT_EX)); if (s_rootLocations.IsDefault)
{
s_rootLocations = ImmutableArray.Create(GetLocation(ASM_CACHE.ROOT), GetLocation(ASM_CACHE.ROOT_EX));
}
return s_rootLocations;
}
} }
private static unsafe string GetLocation(ASM_CACHE gacId) private static unsafe string GetLocation(ASM_CACHE gacId)
...@@ -105,7 +111,7 @@ private static unsafe string GetLocation(ASM_CACHE gacId) ...@@ -105,7 +111,7 @@ private static unsafe string GetLocation(ASM_CACHE gacId)
throw Marshal.GetExceptionForHR(hr); throw Marshal.GetExceptionForHR(hr);
} }
byte[] data = new byte[((int)characterCount + 1) * 2]; byte[] data = new byte[(characterCount + 1) * 2];
fixed (byte* p = data) fixed (byte* p = data)
{ {
hr = GetCachePath(gacId, p, ref characterCount); hr = GetCachePath(gacId, p, ref characterCount);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
...@@ -257,9 +258,7 @@ private static MetadataReferenceResolver CreateMetadataReferenceResolver(IMetada ...@@ -257,9 +258,7 @@ private static MetadataReferenceResolver CreateMetadataReferenceResolver(IMetada
return new RuntimeMetadataReferenceResolver( return new RuntimeMetadataReferenceResolver(
new RelativePathResolver(searchPaths, baseDirectory), new RelativePathResolver(searchPaths, baseDirectory),
string.IsNullOrEmpty(packagesDirectory) ? null : new NuGetPackageResolverImpl(packagesDirectory), string.IsNullOrEmpty(packagesDirectory) ? null : new NuGetPackageResolverImpl(packagesDirectory),
new GacFileResolver( GacFileResolver.IsAvailable ? new GacFileResolver(preferredCulture: CultureInfo.CurrentCulture) : null,
architectures: GacFileResolver.Default.Architectures, // TODO (tomat)
preferredCulture: System.Globalization.CultureInfo.CurrentCulture), // TODO (tomat)
(path, properties) => metadataService.GetReference(path, properties)); (path, properties) => metadataService.GetReference(path, properties));
} }
......
...@@ -169,13 +169,12 @@ private MetadataReferenceResolver CreateMetadataReferenceResolver(ImmutableArray ...@@ -169,13 +169,12 @@ private MetadataReferenceResolver CreateMetadataReferenceResolver(ImmutableArray
var packagesDirectory = string.IsNullOrEmpty(userProfilePath) ? var packagesDirectory = string.IsNullOrEmpty(userProfilePath) ?
null : null :
Path.Combine(userProfilePath, Path.Combine(".nuget", "packages")); Path.Combine(userProfilePath, Path.Combine(".nuget", "packages"));
return new RuntimeMetadataReferenceResolver( return new RuntimeMetadataReferenceResolver(
new RelativePathResolver(searchPaths, baseDirectory), new RelativePathResolver(searchPaths, baseDirectory),
string.IsNullOrEmpty(packagesDirectory) ? null : new NuGetPackageResolverImpl(packagesDirectory), string.IsNullOrEmpty(packagesDirectory) ? null : new NuGetPackageResolverImpl(packagesDirectory),
new GacFileResolver( GacFileResolver.IsAvailable ? new GacFileResolver(preferredCulture: CultureInfo.CurrentCulture) : null,
architectures: GacFileResolver.Default.Architectures, // TODO (tomat) (path, properties) => _metadataFileProvider.GetReference(path, properties));
preferredCulture: CultureInfo.CurrentCulture), // TODO (tomat)
(path, properties) => _metadataFileProvider.GetReference(path, properties));
} }
private SourceReferenceResolver CreateSourceReferenceResolver(ImmutableArray<string> searchPaths, string baseDirectory) private SourceReferenceResolver CreateSourceReferenceResolver(ImmutableArray<string> searchPaths, string baseDirectory)
......
...@@ -23,7 +23,7 @@ internal override MetadataReferenceResolver GetCommandLineMetadataReferenceResol ...@@ -23,7 +23,7 @@ internal override MetadataReferenceResolver GetCommandLineMetadataReferenceResol
return new RuntimeMetadataReferenceResolver( return new RuntimeMetadataReferenceResolver(
new RelativePathResolver(Arguments.ReferencePaths, Arguments.BaseDirectory), new RelativePathResolver(Arguments.ReferencePaths, Arguments.BaseDirectory),
null, null,
new GacFileResolver(GacFileResolver.Default.Architectures, CultureInfo.CurrentCulture), GacFileResolver.IsAvailable ? new GacFileResolver(preferredCulture: CultureInfo.CurrentCulture) : null,
(path, properties) => (path, properties) =>
{ {
loggerOpt?.AddRead(path); loggerOpt?.AddRead(path);
......
...@@ -25,7 +25,7 @@ internal sealed class RuntimeMetadataReferenceResolver : MetadataReferenceResolv ...@@ -25,7 +25,7 @@ internal sealed class RuntimeMetadataReferenceResolver : MetadataReferenceResolv
internal RuntimeMetadataReferenceResolver( internal RuntimeMetadataReferenceResolver(
ImmutableArray<string> searchPaths, ImmutableArray<string> searchPaths,
string baseDirectory) string baseDirectory)
: this(new RelativePathResolver(searchPaths, baseDirectory), null, GacFileResolver.Default) : this(new RelativePathResolver(searchPaths, baseDirectory), null, GacFileResolver.IsAvailable ? new GacFileResolver() : null)
{ {
} }
......
...@@ -19,7 +19,7 @@ Namespace Microsoft.CodeAnalysis.Scripting.Hosting.VisualBasic ...@@ -19,7 +19,7 @@ Namespace Microsoft.CodeAnalysis.Scripting.Hosting.VisualBasic
Return New RuntimeMetadataReferenceResolver( Return New RuntimeMetadataReferenceResolver(
New RelativePathResolver(Arguments.ReferencePaths, Arguments.BaseDirectory), New RelativePathResolver(Arguments.ReferencePaths, Arguments.BaseDirectory),
Nothing, Nothing,
New GacFileResolver(GacFileResolver.Default.Architectures, CultureInfo.CurrentCulture), If(GacFileResolver.IsAvailable, New GacFileResolver(preferredCulture:=CultureInfo.CurrentCulture), Nothing),
Function(path, properties) Function(path, properties)
loggerOpt?.AddRead(path) loggerOpt?.AddRead(path)
Return MetadataReference.CreateFromFile(path) Return MetadataReference.CreateFromFile(path)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册