diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index b7643cfaf..17c690f46 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -147,6 +147,8 @@ namespace ICSharpCode.Decompiler.Metadata internal static (TargetFrameworkIdentifier, Version) ParseTargetFramework(string targetFramework) { + if (string.IsNullOrEmpty(targetFramework)) + return (TargetFrameworkIdentifier.NETFramework, ZeroVersion); string[] tokens = targetFramework.Split(','); TargetFrameworkIdentifier identifier; diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 8c1ae5e6d..234b8be09 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -210,6 +210,11 @@ namespace ICSharpCode.Decompiler.TypeSystem InitializeAsync(mainModule, assemblyResolver, typeSystemOptions).GetAwaiter().GetResult(); } + static readonly string[] implicitReferences = new[] { + "System.Runtime.InteropServices", + "System.Runtime.CompilerServices.Unsafe" + }; + private async Task InitializeAsync(PEFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) { // Load referenced assemblies and type-forwarder references. @@ -217,10 +222,12 @@ namespace ICSharpCode.Decompiler.TypeSystem var referencedAssemblies = new List(); var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference, Task ResolveTask)>(); var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) => - reference.IsAssembly ? "A:" + ((AssemblyReference)reference.Reference).FullName : + reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName : "M:" + reference.Reference); var assemblyReferencesInQueue = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer); var mainMetadata = mainModule.Metadata; + var tfm = mainModule.DetectTargetFrameworkId(); + var (identifier, version) = UniversalAssemblyResolver.ParseTargetFramework(tfm); foreach (var h in mainMetadata.GetModuleReferences()) { try @@ -268,6 +275,27 @@ namespace ICSharpCode.Decompiler.TypeSystem } } } + if (assemblyReferenceQueue.Count == 0) + { + // For .NET Core and .NET 5 and newer, we need to pull in implicit references which are not included in the metadata, + // as they contain compile-time-only types, such as System.Runtime.InteropServices.dll (for DllImport, MarshalAs, etc.) + switch (identifier) + { + case TargetFrameworkIdentifier.NETCoreApp: + case TargetFrameworkIdentifier.NETStandard: + case TargetFrameworkIdentifier.NET: + foreach (var item in implicitReferences) + { + var existing = referencedAssemblies.FirstOrDefault(asm => asm.Name == item); + if (existing == null) + { + AddToQueue(true, mainModule, AssemblyNameReference.Parse(item + ", Version=" + version.ToString(3) + ".0, Culture=neutral")); + } + } + break; + } + + } } var mainModuleWithOptions = mainModule.WithOptions(typeSystemOptions); var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(typeSystemOptions)); @@ -294,7 +322,7 @@ namespace ICSharpCode.Decompiler.TypeSystem Task asm; if (isAssembly) { - asm = assemblyResolver.ResolveAsync((AssemblyReference)reference); + asm = assemblyResolver.ResolveAsync((IAssemblyReference)reference); } else {