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.
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.
User contributions licensed under CC BY-SA 3.0