Last active
August 29, 2015 13:59
-
-
Save vbfox/10960162 to your computer and use it in GitHub Desktop.
DOES NOT WORK, GENERATED IL DOES NOT CONTAIN THE EXPECTED CALL. An exploration on how a mock framework can get a call to a method without specifying the arguments and then mock the real call. The C# compiler make it hard as method groups can't appear anywhere in the language. Well except in one place it seem...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
IFoo foo = new Foo(); | |
A.CallMethodWithAnyArgs(() => A.Hack(__arglist(foo.Bar))); | |
} | |
public static class A | |
{ | |
public static void CallMethodWithAnyArgs(Action callSpecification) | |
{ | |
// Can't use the expression version as expression trees can't contain arglist calls, but the IL of "callSpecification" | |
// is available and can be disasembled to try to find the call... | |
// (It's invalid and would throw BadImageFormatException if executed but it is still readable) | |
callSpecification.Method.Disassemble().Dump(); | |
// The disasm doesn't show any reference to foo.Bar, did the compiler generate nothing | |
// or is it just the disasm that can't interpret it ? | |
// | |
// IL_0000: call UserQuery+A.Hack | |
// IL_0005: nop | |
// IL_0006: ret | |
// Manual disasm | |
var body = callSpecification.Method.GetMethodBody(); | |
var ilBytes = body.GetILAsByteArray(); | |
string.Join(" ", ilBytes.Select(b => b.ToString("X2"))).Dump(); | |
if ((ilBytes[0] != (byte)OpCodes.Call.Value) && (ilBytes[0] != (byte)OpCodes.Callvirt.Value)) | |
{ | |
throw new Exception("Not a method call"); | |
} | |
int token = BitConverter.ToInt32(ilBytes, 1); | |
var field = callSpecification.Method.Module.ResolveMethod(token); | |
field.Dump(); | |
// Sadly it only contains a call to A.Hack, no trace of foo.Bar :-( | |
// Compiler bug, but useless compiler bug... | |
} | |
public static void Hack(__arglist) | |
{ | |
// Marker method | |
} | |
} | |
interface IFoo | |
{ | |
int Bar(int i); | |
bool Bar(float f); | |
} | |
class Foo : IFoo | |
{ | |
public int Bar(int i) | |
{ | |
return 0; | |
} | |
public bool Bar(float f) | |
{ | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment