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

Avoid accessing GAC when not available (on CoreCLR)

上级 df852712
......@@ -76,7 +76,7 @@ private static class _Assembly
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
.GetTypeInfo()
......@@ -89,8 +89,8 @@ private static class _ResolveEventArgs
private static class _AppDomain
{
internal static readonly Type Type = Type.GetType("System.AppDomain", throwOnError: false);
internal static readonly Type ResolveEventHandlerType = Type.GetType("System.ResolveEventHandler", throwOnError: false);
internal static readonly Type Type = ReflectionUtilities.TryGetType("System.AppDomain");
internal static readonly Type ResolveEventHandlerType = ReflectionUtilities.TryGetType("System.ResolveEventHandler");
internal static readonly MethodInfo get_CurrentDomain = Type
.GetTypeInfo()
......
......@@ -10,17 +10,30 @@ namespace Roslyn.Utilities
{
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>
/// 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.
/// </summary>
public static Type GetTypeFromEither(string contractName, string desktopName)
{
var type = Type.GetType(contractName, throwOnError: false);
var type = TryGetType(contractName);
if (type == null)
{
type = Type.GetType(desktopName, throwOnError: false);
type = TryGetType(desktopName);
}
return type;
......
......@@ -6,7 +6,6 @@
namespace Roslyn.Utilities
{
/// <summary>
/// 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
......@@ -14,13 +13,20 @@ namespace Roslyn.Utilities
/// </summary>
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 readonly Type Type =
Type.GetType("System.Text.CodePagesEncodingProvider, " +
"System.Text.Encoding.CodePages, " +
"Version=4.0.0.0, Culture=neutral, " +
"PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
internal static readonly Type Type = ReflectionUtilities.TryGetType(
"System.Text.CodePagesEncodingProvider, " +
"System.Text.Encoding.CodePages, " +
"Version=4.0.0.0, Culture=neutral, " +
"PublicKeyToken=b03f5f7f11d50a3a");
private static PropertyInfo s_instance = Type
?.GetTypeInfo()
......
......@@ -11,37 +11,46 @@
namespace Microsoft.CodeAnalysis.Scripting.Hosting
{
/// <summary>
/// Extends MetadataFileReferenceResolver to enable resolution of assembly
/// simple names in the GAC.
/// Resolves assembly identities in Global Assembly Cache.
/// </summary>
internal sealed class GacFileResolver : IEquatable<GacFileResolver>
{
/// <summary>
/// Architecture filter used when resolving assembly references.
/// Returns true if GAC is available on the platform.
/// </summary>
public ImmutableArray<ProcessorArchitecture> Architectures { get; }
public static bool IsAvailable => CoreClrShim.AssemblyLoadContext.Type == null;
/// <summary>
/// CultureInfo used when resolving assembly references.
/// Architecture filter used when resolving assembly references.
/// </summary>
public CultureInfo PreferredCulture { get; }
public ImmutableArray<ProcessorArchitecture> Architectures { get; }
/// <summary>
/// A resolver that is configured to resolve against the GAC associated
/// with the bitness of the currently executing process.
/// <see cref="CultureInfo"/> used when resolving assembly references, or null to prefer no culture.
/// </summary>
internal static GacFileResolver Default = new GacFileResolver(
architectures: GlobalAssemblyCache.CurrentArchitectures,
preferredCulture: null);
public CultureInfo PreferredCulture { get; }
/// <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>
/// <param name="architectures">Supported architectures used to filter GAC assemblies.</param>
/// <param name="preferredCulture">A culture to use when choosing the best assembly from
/// 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;
PreferredCulture = preferredCulture;
}
......
......@@ -87,13 +87,19 @@ private enum ASM_CACHE
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>(
GetLocation(ASM_CACHE.ROOT),
GetLocation(ASM_CACHE.ROOT_EX));
get
{
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)
......@@ -105,7 +111,7 @@ private static unsafe string GetLocation(ASM_CACHE gacId)
throw Marshal.GetExceptionForHR(hr);
}
byte[] data = new byte[((int)characterCount + 1) * 2];
byte[] data = new byte[(characterCount + 1) * 2];
fixed (byte* p = data)
{
hr = GetCachePath(gacId, p, ref characterCount);
......
......@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
......@@ -257,9 +258,7 @@ private static MetadataReferenceResolver CreateMetadataReferenceResolver(IMetada
return new RuntimeMetadataReferenceResolver(
new RelativePathResolver(searchPaths, baseDirectory),
string.IsNullOrEmpty(packagesDirectory) ? null : new NuGetPackageResolverImpl(packagesDirectory),
new GacFileResolver(
architectures: GacFileResolver.Default.Architectures, // TODO (tomat)
preferredCulture: System.Globalization.CultureInfo.CurrentCulture), // TODO (tomat)
GacFileResolver.IsAvailable ? new GacFileResolver(preferredCulture: CultureInfo.CurrentCulture) : null,
(path, properties) => metadataService.GetReference(path, properties));
}
......
......@@ -169,13 +169,12 @@ private MetadataReferenceResolver CreateMetadataReferenceResolver(ImmutableArray
var packagesDirectory = string.IsNullOrEmpty(userProfilePath) ?
null :
Path.Combine(userProfilePath, Path.Combine(".nuget", "packages"));
return new RuntimeMetadataReferenceResolver(
new RelativePathResolver(searchPaths, baseDirectory),
new RelativePathResolver(searchPaths, baseDirectory),
string.IsNullOrEmpty(packagesDirectory) ? null : new NuGetPackageResolverImpl(packagesDirectory),
new GacFileResolver(
architectures: GacFileResolver.Default.Architectures, // TODO (tomat)
preferredCulture: CultureInfo.CurrentCulture), // TODO (tomat)
(path, properties) => _metadataFileProvider.GetReference(path, properties));
GacFileResolver.IsAvailable ? new GacFileResolver(preferredCulture: CultureInfo.CurrentCulture) : null,
(path, properties) => _metadataFileProvider.GetReference(path, properties));
}
private SourceReferenceResolver CreateSourceReferenceResolver(ImmutableArray<string> searchPaths, string baseDirectory)
......
......@@ -23,7 +23,7 @@ internal override MetadataReferenceResolver GetCommandLineMetadataReferenceResol
return new RuntimeMetadataReferenceResolver(
new RelativePathResolver(Arguments.ReferencePaths, Arguments.BaseDirectory),
null,
new GacFileResolver(GacFileResolver.Default.Architectures, CultureInfo.CurrentCulture),
GacFileResolver.IsAvailable ? new GacFileResolver(preferredCulture: CultureInfo.CurrentCulture) : null,
(path, properties) =>
{
loggerOpt?.AddRead(path);
......
......@@ -25,7 +25,7 @@ internal sealed class RuntimeMetadataReferenceResolver : MetadataReferenceResolv
internal RuntimeMetadataReferenceResolver(
ImmutableArray<string> searchPaths,
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
Return New RuntimeMetadataReferenceResolver(
New RelativePathResolver(Arguments.ReferencePaths, Arguments.BaseDirectory),
Nothing,
New GacFileResolver(GacFileResolver.Default.Architectures, CultureInfo.CurrentCulture),
If(GacFileResolver.IsAvailable, New GacFileResolver(preferredCulture:=CultureInfo.CurrentCulture), Nothing),
Function(path, properties)
loggerOpt?.AddRead(path)
Return MetadataReference.CreateFromFile(path)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册