| File: Utilities\AssemblyLoadInfo.cs | Web Access |
| Project: Microsoft.Build.Framework.csproj (Microsoft.Build.Framework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.IO; using Microsoft.Build.BackEnd; #nullable disable namespace Microsoft.Build.Shared { /// <summary> /// This class packages information about how to load a given assembly -- an assembly can be loaded by either its assembly /// name (strong or weak), or its filename/path. /// </summary> /// <remarks> /// Uses factory to instantiate correct private class to save space: only one field is ever used of the two. /// </remarks> internal abstract class AssemblyLoadInfo : ITranslatable, IEquatable<AssemblyLoadInfo> { /// <summary> /// This constructor initializes the assembly information. /// </summary> internal static AssemblyLoadInfo Create(string assemblyName, string assemblyFile) { Assumed.True( (assemblyName is null) != (assemblyFile is null), "Exactly one of the assembly name and assembly file/path must be provided."); return assemblyName != null ? FromName(assemblyName) : FromFile(assemblyFile); } internal static AssemblyLoadInfo FromFile(string assemblyFile) { Assumed.NotNullOrEmpty(assemblyFile); return new AssemblyLoadInfoWithFile(assemblyFile); } internal static AssemblyLoadInfo FromName(string assemblyName) { Assumed.NotNullOrEmpty(assemblyName); return new AssemblyLoadInfoWithName(assemblyName); } /// <summary> /// Gets the assembly's identity denoted by its strong/weak name. /// </summary> public abstract string AssemblyName { get; } /// <summary> /// Gets the path to the assembly file. /// </summary> public abstract string AssemblyFile { get; } /// <summary> /// Get the assembly location /// </summary> internal abstract string AssemblyLocation { get; } /// <summary> /// Gets whether this assembly is an inline task assembly that should be loaded from bytes to avoid file locking. /// </summary> internal abstract bool IsInlineTask { get; } /// <summary> /// Computes a hashcode for this assembly info, so this object can be used as a key into /// a hash table. /// </summary> public override int GetHashCode() { return AssemblyLocation.GetHashCode(); } public bool Equals(AssemblyLoadInfo other) { return Equals((object)other); } /// <summary> /// Determines if two AssemblyLoadInfos are effectively the same. /// </summary> public override bool Equals(Object obj) { if (obj == null) { return false; } AssemblyLoadInfo otherAssemblyInfo = obj as AssemblyLoadInfo; if (otherAssemblyInfo == null) { return false; } return (this.AssemblyName == otherAssemblyInfo.AssemblyName) && (this.AssemblyFile == otherAssemblyInfo.AssemblyFile); } public void Translate(ITranslator translator) { Assumed.Equal(translator.Mode, TranslationDirection.WriteToStream, "write only"); string assemblyName = AssemblyName; string assemblyFile = AssemblyFile; translator.Translate(ref assemblyName); translator.Translate(ref assemblyFile); } public static AssemblyLoadInfo FactoryForTranslation(ITranslator translator) { string assemblyName = null; string assemblyFile = null; translator.Translate(ref assemblyName); translator.Translate(ref assemblyFile); return Create(assemblyName, assemblyFile); } /// <summary> /// Assembly represented by name /// </summary> [DebuggerDisplay("{AssemblyName}")] private sealed class AssemblyLoadInfoWithName : AssemblyLoadInfo { /// <summary> /// Assembly name /// </summary> private string _assemblyName; /// <summary> /// Constructor /// </summary> internal AssemblyLoadInfoWithName(string assemblyName) { _assemblyName = assemblyName; } /// <summary> /// Gets the assembly's identity denoted by its strong/weak name. /// </summary> public override string AssemblyName { get { return _assemblyName; } } /// <summary> /// Gets the path to the assembly file. /// </summary> public override string AssemblyFile { get { return null; } } /// <summary> /// Get the assembly location /// </summary> internal override string AssemblyLocation { get { return _assemblyName; } } /// <summary> /// Gets whether this assembly is an inline task assembly. /// Assembly names are never inline tasks. /// </summary> internal override bool IsInlineTask { get { return false; } } } /// <summary> /// Assembly info that uses a file path /// </summary> [DebuggerDisplay("{AssemblyFile}")] private sealed class AssemblyLoadInfoWithFile : AssemblyLoadInfo { /// <summary> /// Path to assembly /// </summary> private string _assemblyFile; /// <summary> /// Constructor /// </summary> internal AssemblyLoadInfoWithFile(string assemblyFile) { Assumed.True(Path.IsPathRooted(assemblyFile), "Assembly file path should be rooted"); _assemblyFile = assemblyFile; } /// <summary> /// Gets the assembly's identity denoted by its strong/weak name. /// </summary> public override string AssemblyName { get { return null; } } /// <summary> /// Gets the path to the assembly file. /// </summary> public override string AssemblyFile { get { return _assemblyFile; } } /// <summary> /// Get the assembly location /// </summary> internal override string AssemblyLocation { get { return _assemblyFile; } } /// <summary> /// Gets whether this assembly is an inline task assembly. /// Detects inline tasks by checking if the file path ends with the inline task suffix. /// </summary> internal override bool IsInlineTask { get { return _assemblyFile?.EndsWith(TaskFactoryUtilities.InlineTaskSuffix, StringComparison.OrdinalIgnoreCase) == true; } } } } }