微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

InvalidProgramException:包装器动态方法对象中的无效IL代码:GetField:IL_0000:ret

如何解决InvalidProgramException:包装器动态方法对象中的无效IL代码:GetField:IL_0000:ret

标题中所述。但是,我正在尝试这样做:
  delegate char[] FieldDelegate();
   
  private FieldDelegate Get_InternalBuffer(StringBuilder sb)
  {
     var sbType = sb.GetType();
     var fieldInfo = sbType.GetField("m_ChunkChars",BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
     
     var dynMethod = new Dynamicmethod("GetField",typeof(char[]),new Type[0],true);
     ILGenerator ig = dynMethod.GetILGenerator();
     ig.Emit(OpCodes.ldflda,fieldInfo);
     ig.Emit(OpCodes.Ret);
     return dynMethod.CreateDelegate(typeof(FieldDelegate)) as FieldDelegate;
  }

简短地说,我不知道为什么。我已经检查了仅包含“ char []缓冲区”的类的IL代码,以模拟我在此处执行的操作,它实际上正确地指出了这一点:“ IL_0006:ret”作为单个IL_instruction,所以我在做什么错了? / p>

任何帮助都会很棒!

最诚挚的问候

解决方法

我不确定100%地是您要实现的目标,但是它必须是动态的/使用Emit API吗?

如果没有,这是一种可行的反思方法:

private static Func<char[]> Get_InternalBuffer_Reflection_Only(StringBuilder stringBuilder)
{
   Type sbType = stringBuilder.GetType();
   FieldInfo fieldInfo = sbType.GetField("m_ChunkChars",BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);

   Func<char[]> func = () => (char[])fieldInfo.GetValue(stringBuilder);
   return func;
}

有很多注意事项:

  • 您正在将StringBuilder捕获到Delegate / Func中,并将其生命周期与返回的Delegate / Func联系起来。
  • 每次使用新的StringBuilder时,您都必须支付发射/反射的开销

编辑:

为了提高性能,我认为您可以使用Expression或Emit做到这一点。使用IL时,我不确定如何在动态创建的方法中捕获StringBuilder参数,但是可以稍微更改Delegate以获得相同的结果。

再次查看代码之所以不起作用,是因为您在调用Ldfld时,方法内部实际上没有任何栈。单独的FieldInfo仅描述如何获取值,您仍然需要引用该对象以从中获取值。

更改您的代表可以执行以下操作:

delegate char[] FieldDelegate(StringBuilder sb);

private static FieldDelegate Get_InternalBuffer()
{
    Type sbType = typeof(StringBuilder);
    FieldInfo fieldInfo = sbType.GetField("m_ChunkChars",BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);

    var dynMethod = new DynamicMethod("DynamicGetChunkChars",typeof(char[]),new Type[] { sbType },true);
    ILGenerator ig = dynMethod.GetILGenerator();
    ig.Emit(OpCodes.Ldarg_0);
    ig.Emit(OpCodes.Ldfld,fieldInfo);
    ig.Emit(OpCodes.Ret);
    return dynMethod.CreateDelegate(typeof(FieldDelegate)) as FieldDelegate;
}

static void Main(string[] args)
{
    var sb = new StringBuilder("test123");
    FieldDelegate getBuffer = Get_InternalBuffer();

    char[] ret = getBuffer(sb);

    Console.ReadLine();
}

您将必须使用StringBuilder调用返回的方法。 这也意味着您现在可以缓存返回的方法并重复使用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。