mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
3.6 KiB
97 lines
3.6 KiB
using System; |
|
using System.Linq; |
|
using System.Text.RegularExpressions; |
|
|
|
using ICSharpCode.Decompiler.Metadata; |
|
|
|
namespace ICSharpCode.ILSpy.AddIn |
|
{ |
|
public class AssemblyFileFinder |
|
{ |
|
public static string FindAssemblyFile(Mono.Cecil.AssemblyDefinition assemblyDefinition, string assemblyFile) |
|
{ |
|
string tfi = DetectTargetFrameworkId(assemblyDefinition, assemblyFile); |
|
UniversalAssemblyResolver assemblyResolver; |
|
if (IsReferenceAssembly(assemblyDefinition, assemblyFile)) |
|
{ |
|
assemblyResolver = new UniversalAssemblyResolver(null, throwOnError: false, tfi); |
|
} |
|
else |
|
{ |
|
assemblyResolver = new UniversalAssemblyResolver(assemblyFile, throwOnError: false, tfi); |
|
} |
|
|
|
return assemblyResolver.FindAssemblyFile(AssemblyNameReference.Parse(assemblyDefinition.Name.FullName)); |
|
} |
|
|
|
static readonly string RefPathPattern = @"NuGetFallbackFolder[/\\][^/\\]+[/\\][^/\\]+[/\\]ref[/\\]"; |
|
|
|
public static bool IsReferenceAssembly(Mono.Cecil.AssemblyDefinition assemblyDef, string assemblyFile) |
|
{ |
|
if (assemblyDef.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.ReferenceAssemblyAttribute")) |
|
return true; |
|
|
|
// Try to detect reference assembly through specific path pattern |
|
var refPathMatch = Regex.Match(assemblyFile, RefPathPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); |
|
return refPathMatch.Success; |
|
} |
|
|
|
static readonly string DetectTargetFrameworkIdRefPathPattern = |
|
@"(Reference Assemblies[/\\]Microsoft[/\\]Framework[/\\](?<1>.NETFramework)[/\\]v(?<2>[^/\\]+)[/\\])" + |
|
@"|((NuGetFallbackFolder|packs|.nuget[/\\]packages)[/\\](?<1>[^/\\]+)\\(?<2>[^/\\]+)([/\\].*)?[/\\]ref[/\\])"; |
|
|
|
public static string DetectTargetFrameworkId(Mono.Cecil.AssemblyDefinition assembly, string assemblyPath = null) |
|
{ |
|
if (assembly == null) |
|
throw new ArgumentNullException(nameof(assembly)); |
|
|
|
const string TargetFrameworkAttributeName = "System.Runtime.Versioning.TargetFrameworkAttribute"; |
|
|
|
foreach (var attribute in assembly.CustomAttributes) |
|
{ |
|
if (attribute.AttributeType.FullName != TargetFrameworkAttributeName) |
|
continue; |
|
if (attribute.HasConstructorArguments) |
|
{ |
|
if (attribute.ConstructorArguments[0].Value is string value) |
|
return value; |
|
} |
|
} |
|
|
|
// Optionally try to detect target version through assembly path as a fallback (use case: reference assemblies) |
|
if (assemblyPath != null) |
|
{ |
|
/* |
|
* Detected path patterns (examples): |
|
* |
|
* - .NETFramework -> C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll |
|
* - .NETCore -> C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll |
|
* -> C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.0.0\ref\netcoreapp3.0\System.Runtime.Extensions.dll |
|
* - .NETStandard -> C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll |
|
*/ |
|
var pathMatch = Regex.Match(assemblyPath, DetectTargetFrameworkIdRefPathPattern, |
|
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); |
|
if (pathMatch.Success) |
|
{ |
|
var type = pathMatch.Groups[1].Value; |
|
var version = pathMatch.Groups[2].Value; |
|
|
|
if (type == ".NETFramework") |
|
{ |
|
return $".NETFramework,Version=v{version}"; |
|
} |
|
else if (type.ToLower().Contains("netcore")) |
|
{ |
|
return $".NETCoreApp,Version=v{version}"; |
|
} |
|
else if (type.ToLower().Contains("netstandard")) |
|
{ |
|
return $".NETStandard,Version=v{version}"; |
|
} |
|
} |
|
} |
|
|
|
return string.Empty; |
|
} |
|
} |
|
}
|
|
|