使用Reflection.Emit </t>为IEnumerable <t>调用“Current”

时间:2014-04-21 13:48:14

标签: c# reflection.emit il

请告知我如何建立Current的{​​{1}}和MoveNext的财产电话。

目标

我希望得到类似的内容:

IEnumerable<byte>

变式1

这是代码:

var bytesEnumerator = byteArray.EnumerateArray();
var controlByte = bytesEnumerator.Current;
bytesEnumerator.MoveNext();

失败:

  

{&#34;收藏品已被修改;枚举操作可能无法执行。&#34;}

变式2

当我按地址存储枚举器时(Ldloc_S - &gt; Ldloca_S)

LocalBuilder lbBytesEnumerator = il.DeclareLocal(typeof (IEnumerator<byte>));
// Get enumerator over bytes
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, typeof(ByteConverter).GetMethod("EnumerateArray"), new[] { typeof(byte[]) } );
il.Emit(OpCodes.Stloc, lbBytesEnumerator);

.......
il.Emit(OpCodes.Ldloc_S, lbBytesEnumerator);
il.EmitCall(OpCodes.Call, typeof(IEnumerator<byte>).GetProperty("Current").GetGetMethod(), null);
LocalBuilder lbControlByte = il.DeclareLocal(propertyInfo.PropertyType);
il.Emit(OpCodes.Stloc, lbControlByte);


// Enumerator Move Next
il.Emit(OpCodes.Ldloc_S, lbBytesEnumerator);
il.EmitCall(OpCodes.Call, typeof(List<byte>.Enumerator).GetMethod("MoveNext"), null);
il.Emit(OpCodes.Pop);

失败了:

  

{&#34;尝试读取或写入受保护的内存。这通常表明其他内存已损坏。&#34;}

更新

枚举数组返回的Enumerator不是基于List而是它产生的结果:

......
il.Emit(OpCodes.Ldloca_S, lbBytesEnumerator);
il.EmitCall(OpCodes.Call, typeof(IEnumerator<byte>).GetProperty("Current").GetGetMethod(), null);
LocalBuilder lbControlByte = il.DeclareLocal(propertyInfo.PropertyType);
il.Emit(OpCodes.Stloc, lbControlByte);

2 个答案:

答案 0 :(得分:0)

如果要调用代码,则必须使用Types和MethodInfos,而不是TypeBuilders和MethodBuilders。

因此,您需要CreateType()然后使用该Type及其方法:

var generatedType = typeBuilder.CreateType();

var funcType = typeof(Func<,>).MakeGenericType(
generatedType, typeof(IEnumerable<string>));
var d = generatedType.GetMethod("MoveNext").CreateDelegate(funcType);

答案 1 :(得分:0)

固定代码:

                // Control byte
                il.Emit(OpCodes.Ldloc, lbBytesEnumerator);
                il.EmitCall(OpCodes.Callvirt, typeof(IEnumerator<byte>).GetProperty("Current").GetGetMethod(), null);
                LocalBuilder lbControlByte = il.DeclareLocal(propertyInfo.PropertyType);
                il.Emit(OpCodes.Stloc, lbControlByte);
                // Enumerator Move Next
                il.Emit(OpCodes.Ldloc, lbBytesEnumerator);
                il.EmitCall(OpCodes.Callvirt, typeof(IEnumerator).GetMethod("MoveNext"), null);
                il.Emit(OpCodes.Pop);