ltrzesniewski / InlineIL.Fody

Inject arbitrary IL code at compile time.
MIT License
240 stars 17 forks source link

MethodRef to overloaded generic method #10

Closed phdjonov closed 5 years ago

phdjonov commented 5 years ago

I'm probably just missing the obvious, but I can't figure out how to emit a call to a specific overload of a generic method.

For instance, given something like the following:

static class C
{
    static ref T M<T>(T[] a, int b); // #1
    static ref T M<T>(T[] a, uint b); // #2
    static ref T M<T>(T[] a, IntPtr b); / /#3
    static ref T M<T>(T[] a, UIntPtr b); // #4
}

How would I emit a call to overload 4, instantiated for, say, string?

Emit.Call(new MethodRef(typeof(C), nameof(C.M)).MakeGenericMethod(typeof(string))); 
//error: ambiguous function, as expected

Emit.Call(new MethodRef(typeof(C), nameof(C.M), typeof(???), typeof(UIntPtr)).MakeGenericMethod(typeof(string))); 
//what goes in the ??? - string[] doesn't work (as expected)

I'm trying to avoid popping variables, calling through regular C# code, and then pushing the result as this generates unnecessary locals and instructions, and I seem to be right at the edge of what the JIT will optimize well and want to stay under that mark.

Thanks.

ltrzesniewski commented 5 years ago

Sorry, but that looks like something I forgot to implement. Oops 😰 I'll add support for this in the next version, but you'll need to wait a few weeks. Thanks for the report!

phdjonov commented 5 years ago

Hey thanks for the quick response!

No worries about the wait. I'm just looking forward to ripping out the ugly workaround whenever you publish the update.

Cheers!

ltrzesniewski commented 5 years ago

I'll release v1.2.0 with the fix today. Please tell me if it works for you as I've changed how things work with generics quite a bit.

You need to use the following code for your example case:

IL.Emit.Call(
    new MethodRef(
        typeof(C),
        nameof(C.M),
        TypeRef.MethodGenericParameters[0].MakeArrayType(),
        typeof(UIntPtr)
    ).MakeGenericMethod(typeof(string))
);

See #11 for details.

phdjonov commented 5 years ago

That's working perfectly. Thanks!