ILSpy
ILSpy copied to clipboard
Potential issue in GetDefinition() returning UnknownType
Steps to reproduce
- The following code runs just fine and resolve the type:
System.Reflection.Assembly.LoadFrom(@"C:\WINDOWS\Microsoft.Net\assembly\GAC_64\Microsoft.AppV.AppvClientComConsumer\v4.0_10.0.0.0__31bf3856ad364e35\Microsoft.AppV.AppvClientComConsumer.dll").GetType(@"msclr.interop.context_node<char const \*\,System::String ^>")
- However, when running the following code, the result of
GetDefinition()isnullso I cannot get itsMetadataTokenand useDecompileAsString:
var mydecompiler = new ICSharpCode.Decompiler.CSharp.CSharpDecompiler(@"C:\WINDOWS\Microsoft.Net\assembly\GAC_64\Microsoft.AppV.AppvClientComConsumer\v4.0_10.0.0.0__31bf3856ad364e35\Microsoft.AppV.AppvClientComConsumer.dll", new ICSharpCode.Decompiler.DecompilerSettings() { });
var name = new ICSharpCode.Decompiler.TypeSystem.FullTypeName(@"msclr.interop.context_node<char const \*\,System::String ^>");
var typeInfo = mydecompiler.TypeSystem.MainModule.Compilation.FindType(name).GetDefinition();
Console.WriteLine(typeInfo != null);
The problem seems to come from the following line of code which does not resolve the type: https://github.com/icsharpcode/ILSpy/blob/d2cc9e0989649451e4a6f4200bab5e84c3a24ba9/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs#L444
Details
Product in use: The ICSharpCode.Decompiler NuGet package
Version in use: v7.2.1.6856 and ICSharpCode.Decompiler.8.0.0.7124-preview2
Have you tried using the full type name without any escape sequences, e.g. @"msclr.interop.context_node<char const *,System::String ^>"?
This is how the name is specified in the metadata tables:

As far as I know, the only special characters interpreted by the FullTypeName constructor are:
.for separating namespaces and types.+for denoting nested types`for denoting type parameter counts
This is because the library is primarily targetted at C#.
@dgrunwald do you think it is necessary to add compatibility to the logic used here? https://github.com/dotnet/runtime/blob/e55c908229e36f99a52745d4ee85316a0e8bb6a2/src/mono/System.Private.CoreLib/src/System/TypeNameParser.cs#L256
Have you tried using the full type name without any escape sequences, e.g.
@"msclr.interop.context_node<char const *,System::String ^>"?
The code was completely automated so I took a snapshot of that and added an @ by mistake instead of removing the \ character. I will test again and report back but I think this works fine and it was my mistake :) I just need to figure out why the value in my program was escaped. Thank you.
After all it seems to be a bug I think in ILSpy. It seems the way .NET handles it is different than ILSpy. The following screenshot shows how in .NET it escapes characters such as , but as they are not escaped in ILSpy, iteration will fail:

In the example above, the cliext.Enum_iterator<System::Collections::IEnumerable\,System::Collections::IEnumerator\,System::Object ^> won't be found and we have to use cliext.Enum_iterator<System::Collections::IEnumerable,System::Collections::IEnumerator,System::Object ^>
In my code, the workaround was easy (t is a Type object):
var name = new FullTypeName(t.FullName.Replace(@"\",""));
FullTypeName is just meant to split a string, it doesn't have any escaping logic.
Parsing more complicated type names (like the TypeNameParser @siegfriedpammer linked) is handled in ReflectionHelper.ParseReflectionName -- that's where we should add support for \ escapes (I had no idea those existed).