IL Method Call always return null

1

i'm trying do make a custom proxy using Reflection Emit (IL Code). Everything is working fine, but when i call a second method i always get no result and i get an execption trying to unbox a null value (NullReferenceException).

Here is the IL Code Generated dynamically using Emit. (I've commented the important parts)

.method public hidebysig newslot virtual final 
        instance int32  TestCall(int32 A_1,
                                 int32 A_2) cil managed
{
  // Code size       155 (0x9b)
  .maxstack  5
  .locals init (class [mscorlib]System.Reflection.MethodInfo V_0,
           class [BaseProxy.Console]BaseProxy.Console.TestClass V_1,
           object[] V_2,
           bool V_3,
           object V_4)
  IL_0000:  ldc.i4     0x2
  IL_0005:  newarr     [mscorlib]System.Object
  IL_000a:  stloc.2
  IL_000b:  ldloc.2
  IL_000c:  ldc.i4     0x0
  IL_0011:  ldarg      A_1
  IL_0015:  nop
  IL_0016:  nop
  IL_0017:  box        [mscorlib]System.Int32
  IL_001c:  stelem.ref
  IL_001d:  ldloc.2
  IL_001e:  ldc.i4     0x1
  IL_0023:  ldarg      A_2
  IL_0027:  nop
  IL_0028:  nop
  IL_0029:  box        [mscorlib]System.Int32
  IL_002e:  stelem.ref
  IL_002f:  ldtoken    [BaseProxy.Console]BaseProxy.Console.TestClass
  IL_0034:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_0039:  ldstr      "TestCall"
  IL_003e:  call       instance class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string)
  IL_0043:  stloc.0
  IL_0044:  ldarg.0
  IL_0045:  ldfld      class [BaseProxy.Console]BaseProxy.Console.TestClass TestClassProxy::wrappedObject
  IL_004a:  stloc.1
  IL_004b:  ldc.i4.1
  IL_004c:  stloc.3
  IL_004d:  ldarg.0
  IL_004e:  ldfld      class [BaseProxy.Console]BaseProxy.Console.BasicInterceptor TestClassProxy::interception
  IL_0053:  ldloc.0
  IL_0054:  ldloc.2
  IL_0055:  ldloc.1
  IL_0056:  ldloca.s   V_3
  IL_0058:  callvirt   instance object [BaseProxy.Console]BaseProxy.Console.BasicInterceptor::Before(class [mscorlib]System.Reflection.MethodInfo,
                                                                                                     object[],
                                                                                                     object,
                                                                                                     bool&) 
  **//Here everything is ok, i can get the result.**
  IL_005d:  box        [mscorlib]System.Object
  IL_0062:  stloc.s    V_4
  IL_0064:  nop
  IL_0065:  ldloc.3
  IL_0066:  brfalse.s  IL_0093
  IL_0068:  ldarg.0
  IL_0069:  ldfld      class [BaseProxy.Console]BaseProxy.Console.TestClass TestClassProxy::wrappedObject
  IL_006e:  ldloc.2
  IL_006f:  ldc.i4     0x0
  IL_0074:  ldelem.ref
  IL_0075:  unbox.any  [mscorlib]System.Int32
  IL_007a:  ldloc.2
  IL_007b:  ldc.i4     0x1
  IL_0080:  ldelem.ref
  IL_0081:  unbox.any  [mscorlib]System.Int32
  IL_0086:  callvirt   instance int32 [BaseProxy.Console]BaseProxy.Console.TestClass::TestCall(int32,
                                                                                               int32)
  **\\This Call Always return nothing (null)**
  IL_008b:  box        [mscorlib]System.Object
  IL_0090:  stloc.s    V_4
  IL_0092:  nop
  IL_0093:  ldloc.s    V_4
  **\\And i get a Exception here because loc 4 is null**
  IL_0095:  unbox.any  [mscorlib]System.Int32
  IL_009a:  ret
} // end of method TestClassProxy::TestCall

The TestCall Method is a very simple method that returns a int32 value. I've placed a break point inside TestCall and its hiting fine.

PEVerify returned me the follwing error:

[IL]: Error: [GeneratedProxyModule.dll : TestClassProxy::TestCall][offset 0x0000008B][found Int32][expected ref 'System.Object'] Unexpected type on the stack.

Any help apretiated. Thanks in advance.

c#
.net
reflection
reflection.emit
asked on Stack Overflow Jul 24, 2012 by Renato Degelo • edited Jul 24, 2012 by Renato Degelo

1 Answer

2

The PEVerify output tells you exactly what the problem is. The box instruction at 8B expected Object on the stack, but at the time, Int32 was there. But we want to have Int32 there, that's what we want to box. So why does box expect Object? Because you told it so. The parameter to box tells it from what type to box, not to what type to box.

So, changing your code to:

IL_008b:  box        [mscorlib]System.Int32

should fix your problem.

Although all the instructions between 8B and 95 look like a complicated way to do nothing (box, store, load, unbox) to me. If you don't have any special reason to have them there, you should just remove them.

answered on Stack Overflow Jul 24, 2012 by svick • edited Aug 19, 2012 by svick

User contributions licensed under CC BY-SA 3.0