I'm trying to get the ldtoken IL method to load a generic instantiation of a generic method within a generic class (say, List.ConvertAll<TOutput>):
ldtoken method instance
class [mscorlib]System.Collections.Generic.List`1<!!0>
[mscorlib]System.Collections.Generic.List`1::ConvertAll<string>(
class [mscorlib]System.Converter`2<!0,!!0>)
This results in an exception:
Unhandled Exception: System.TypeLoadException: Could not load type 'System.Collections.Generic.List`1' from assembly 'TestAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
It's looking in my test assembly for System.Collections.Generic.List, even though it's explicitly declared in mscorlib!
However, loading the uninstantiated method token works:
ldtoken method instance
class [mscorlib]System.Collections.Generic.List`1<!!0>
[mscorlib]System.Collections.Generic.List`1::ConvertAll<[1]>(
class [mscorlib]System.Converter`2<!0,!!0>)
A generic method in a non-generic class works:
ldtoken method void [mscorlib]System.Array::Sort<object>(!!0[])
ldtoken method void [mscorlib]System.Array::Sort<[1]>(!!0[])
What's going on? Is this a bug in .NET? (I've replicated it on the v2 and v4 CLR)
As I mentioned in a comment, I think you need to instantiate the generic type (i.e. there is no such type as System.Collections.Generic.List`1 - just System.Collections.Generic.List`1<object>, etc.).
By playing around with System.Reflection.Emit, it looks like it's possible to use ldtoken with an instantiated or uninstantiated method on an instantiated generic type:
ldtoken method instance
class [mscorlib]System.Collections.Generic.List`1<!!0>
class [mscorlib]System.Collections.Generic.List`1<object>::ConvertAll<[1]>(
class [mscorlib]System.Converter`2<!0,!!0>)
ldtoken method instance
class [mscorlib]System.Collections.Generic.List`1<!!0>
class [mscorlib]System.Collections.Generic.List`1<object>::ConvertAll<string>(
class [mscorlib]System.Converter`2<!0,!!0>)
but not with an uninstantiated generic type. Partition II, section 9.4 of the ECMA CLI spec states that
The CLI does not support partial instantiation of generic types. And generic types shall not appear uninstantiated anywhere in metadata signature blobs.
so perhaps this isn't surprising - there doesn't seem to be any way to use ldtoken with the equivalent of typeof(List<>).GetMethod("ConvertAll").
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With