| File: AssemblyDependency\FrameworkPathResolver.cs | Web Access |
| Project: src\msbuild\src\Tasks\Microsoft.Build.Tasks.csproj (Microsoft.Build.Tasks.Core) |
// 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.Collections.Generic; using Microsoft.Build.Framework; using Microsoft.Build.Shared; #nullable disable namespace Microsoft.Build.Tasks { /// <summary> /// Resolve searchpath type {TargetFrameworkDirectory} /// </summary> internal class FrameworkPathResolver : Resolver { // Paths to FX folders. private readonly string[] _frameworkPaths; // Table of information about framework assemblies. private readonly InstalledAssemblies _installedAssemblies; /// <summary> /// Construct. /// </summary> public FrameworkPathResolver(string[] frameworkPaths, InstalledAssemblies installedAssemblies, string searchPathElement, GetAssemblyName getAssemblyName, FileExists fileExists, GetAssemblyRuntimeVersion getRuntimeVersion, Version targetedRuntimeVesion, TaskEnvironment taskEnvironment) : base(searchPathElement, getAssemblyName, fileExists, getRuntimeVersion, targetedRuntimeVesion, System.Reflection.ProcessorArchitecture.None, false, taskEnvironment) { _frameworkPaths = frameworkPaths; _installedAssemblies = installedAssemblies; } /// <inheritdoc/> public override bool Resolve( AssemblyNameExtension assemblyName, string sdkName, string rawFileNameCandidate, bool isPrimaryProjectReference, bool isImmutableFrameworkReference, bool wantSpecificVersion, string[] executableExtensions, string hintPath, string assemblyFolderKey, List<ResolutionSearchLocation> assembliesConsideredAndRejected, out string foundPath, out bool userRequestedSpecificFile) { foundPath = null; userRequestedSpecificFile = false; if (assemblyName != null) { AssemblyNameExtension assemblyNameToUse = GetHighestVersionInRedist(_installedAssemblies, assemblyName); foreach (string frameworkPath in _frameworkPaths) { string resolvedPath = ResolveFromDirectory(assemblyNameToUse, isPrimaryProjectReference, wantSpecificVersion, executableExtensions, frameworkPath, assembliesConsideredAndRejected); if (resolvedPath != null) { foundPath = resolvedPath; return true; } } } return false; } /// <summary> /// If the version is not set for an assembly reference, go through the redist list and find the highest version for that assembly. /// Make sure when matching the assembly in the redist that we take into account the publicKeyToken and the Culture. /// </summary> internal static AssemblyNameExtension GetHighestVersionInRedist(InstalledAssemblies installedAssemblies, AssemblyNameExtension assemblyName) { AssemblyNameExtension assemblyNameToUse = assemblyName; if (assemblyNameToUse.Version == null && installedAssemblies != null) { // If there are multiple entries in the redist list for this assembly, let's // pick the one with the highest version and resolve it. foreach (AssemblyEntry a in installedAssemblies.FindAssemblyNameFromSimpleName(assemblyName.Name)) { var current = new AssemblyNameExtension(a.FullName); // If the current version is higher than the previously looked at. if (current.Version?.CompareTo(assemblyNameToUse.Version) > 0) { // Only compare the Culture and the public key token, the simple names will ALWAYS be the same and the version we do not care about. if (assemblyName.PartialNameCompare(current, PartialComparisonFlags.Culture | PartialComparisonFlags.PublicKeyToken)) { assemblyNameToUse = current; } } } } return assemblyNameToUse; } } }