|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System;
using System.Collections.Immutable;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Scripting.Hosting
{
/// <summary>
/// Resolves assembly identities in Global Assembly Cache.
/// </summary>
internal sealed class GacFileResolver : IEquatable<GacFileResolver>
{
/// <summary>
/// Returns true if GAC is available on the current platform.
/// </summary>
public static bool IsAvailable
{
get
{
// Since mscorlib may not be loaded from the GAC on Mono, also check if the platform is Mono which supports a GAC.
return
#if !NETCOREAPP
typeof(object).Assembly.GlobalAssemblyCache ||
#endif
PlatformInformation.IsRunningOnMono;
}
}
/// <summary>
/// Architecture filter used when resolving assembly references.
/// </summary>
public ImmutableArray<ProcessorArchitecture> Architectures { get; }
/// <summary>
/// <see cref="CultureInfo"/> used when resolving assembly references, or null to prefer no culture.
/// </summary>
public CultureInfo PreferredCulture { get; }
/// <summary>
/// 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>
/// <exception cref="PlatformNotSupportedException">The platform doesn't support GAC.</exception>
public GacFileResolver(
ImmutableArray<ProcessorArchitecture> architectures = default,
CultureInfo preferredCulture = null)
{
if (!IsAvailable)
{
throw new PlatformNotSupportedException();
}
if (architectures.IsDefault)
{
architectures = GlobalAssemblyCache.CurrentArchitectures;
}
Architectures = architectures;
PreferredCulture = preferredCulture;
}
public string Resolve(string assemblyName)
{
string path;
GlobalAssemblyCache.Instance.ResolvePartialName(assemblyName, out path, Architectures, this.PreferredCulture);
return File.Exists(path) ? path : null;
}
public override int GetHashCode()
{
return Hash.Combine(PreferredCulture, Hash.CombineValues(Architectures));
}
public bool Equals(GacFileResolver other)
{
return ReferenceEquals(this, other) ||
other != null &&
Architectures.SequenceEqual(other.Architectures) &&
PreferredCulture == other.PreferredCulture;
}
public override bool Equals(object obj) => Equals(obj as GacFileResolver);
}
}
|