Skip to content

Instantly share code, notes, and snippets.

@vbfox
Last active August 29, 2015 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vbfox/10960162 to your computer and use it in GitHub Desktop.
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...
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