【问题标题】:DynamicMethod NullReferenceException动态方法 NullReferenceException
【发布时间】:2010-03-12 17:40:30
【问题描述】:

谁能告诉我这里的 IL 代码有什么问题?

IL_0000: nop        
IL_0001: ldarg.1    
IL_0002: isinst     MyXmlWriter
IL_0007: stloc.0    
IL_0008: ldloc.0    
IL_0009: ldarg.2    
IL_000a: ldind.ref  
IL_000b: unbox.any  TestEnum
IL_0010: ldfld      Int64 value__/FastSerializer.TestEnum
IL_0015: callvirt   Void WriteValue(Int64)/System.Xml.XmlWriter
IL_001a: nop        
IL_001b: ret       

我在这里发疯了,因为我已经编写了一个测试应用程序,它与上面做同样的事情,但是在 C# 和反射器中,其中的 IL 代码看起来就像我上面的 DynamicMethod 的 IL 代码(除了我的测试C# 应用程序使用带有公共字段的 TestStruct,而不是上面枚举中的私有值字段,但我已将 skipVisibility 设置为 true)...

我得到一个 NullReferenceException。

我的 DynamicMethod 的签名是:

public delegate void DynamicWrite(IMyXmlWriter writer, ref object value, MyContract contract);

我生成这样的方法:

List<Type> parameterTypes = new List<Type> { 
   typeof(DMBuilder), 
   typeof(IDynamicSerializationWriter), 
   typeof(object).MakeByRefType(), 
   typeof(MyContract) 
}; 
DynamicMethod dm = new DynamicMethod(string.Format(
  "Write_{0}", 
  contract.TypeName), 
  typeof(void), 
  parameterTypes.ToArray(), 
  typeof(DMBuilder), 
  true
);

var d = dm.CreateDelegate(typeof(DynamicWrite), this);
d(x,y); 

而且我绝对不会传入任何空值。

提前致谢!

【问题讨论】:

标签: c# exception cil verify dynamicmethod


【解决方案1】:

不得不猜测,我赌的是你发出一个静态方法,但在你的 C# 代码中使用了一个实例方法。肯定有一个“this”参数(arg.0),但从未使用过。将其声明为静态,再次编译和反汇编。

【讨论】:

  • 我确实将它用作实例上的 DynamicMethod,但我认为我不会将其作为静态方法发出:List parameterTypes = new List { typeof(DMBuilder) , typeof(IDynamicSerializationWriter), typeof(object).MakeByRefType(), typeof(MyContract) }; DynamicMethod dm = new DynamicMethod(string.Format("Write_{0}", contract.TypeName), typeof(void), parameterTypes.ToArray(), typeof(DMBuilder), true);这不正确吗?
  • @Jeff:这是一个静态方法。它解释了您的问题,您的代码使用了错误的参数。
  • 对不起,我想我没有完全理解。我应该包括下一行: var d = dm.CreateDelegate(typeof(DynamicWrite), this) 然后我调用如下: d(x,y);我应该做些什么不同的事情?谢谢。
  • 您传递给 CreateDelegate 的“this”类型是什么?您没有将其声明为该方法的参数。不要忘记:实例方法有一个隐藏的额外第一个参数,用于传递对象引用。
  • 这是一个 DMBuilder 实例,我在上面的 List 中作为 DynamicMethod 的类型参数传入的第一个参数,委托签名本身没有这个第一个参数(因为它是隐藏的)。
【解决方案2】:
IL_0002 isinst 

此指令在 local.0 中压入一个空值。 你可以删除它。

【讨论】:

    猜你喜欢
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 2011-05-07
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    • 2011-08-15
    相关资源
    最近更新 更多