C# emit call to generic method
Asked Answered
O

1

5

Having the class

class C
{
    public T Get<T>()
    {
        return default;
    }

    public void M()
    {
        int i = this.Get<Int32>();
    }
}

I want to generate the body of M at runtime using Reflection.Emit and ILGenerator so that it exactly resembles what is shown above.


What I tried is

ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Call, typeof(C).GetMethod(nameof(C.Get), BindingFlags.Instance));

which yields

ldarg.0
call instance !!0 C::Get<M0>(string)
//                       ^^
ret

but I need to get

ldarg.0
call instance !!0 C::Get<int32>(string)
//                       ^^^^^
ret

(note the different type parameters in the call to C.Get<T>)


When emitting a call to a generic cfunction, how do I pass the type of the generic parameter (i.e. get rid of the M0 and have it say int32 instead)?

Outrage answered 21/11, 2018 at 7:46 Comment(0)
N
11

You need to substitute the type arguments with MakeGenericMethod:

ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit
( 
  OpCodes.Call, 
  typeof(C)
  .GetMethod(nameof(C.Get), BindingFlags.Instance)
  .MakeGenericMethod(typeof(int))
);
Neoplasm answered 21/11, 2018 at 7:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.