C# 为IEnumerable调用'Current'<;T>;使用Reflection.Emit

C# 为IEnumerable调用'Current'<;T>;使用Reflection.Emit,c#,reflection.emit,il,C#,Reflection.emit,Il,请告知如何构建IEnumerable的属性Current和MoveNext的调用 目标 我想买一些像这样的东西: var bytesEnumerator = byteArray.EnumerateArray(); var controlByte = bytesEnumerator.Current; bytesEnumerator.MoveNext(); 变式1 以下是代码: LocalBuilder lbBytesEnumerator = il.DeclareLocal(typeof (IEn

请告知如何构建
IEnumerable
的属性
Current
MoveNext
的调用

目标 我想买一些像这样的东西:

var bytesEnumerator = byteArray.EnumerateArray();
var controlByte = bytesEnumerator.Current;
bytesEnumerator.MoveNext();
变式1 以下是代码:

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);
LocalBuilder lbBytesEnumerator=il.DeclareLocal(typeof(IEnumerator));
//获取超过字节的枚举数
il.Emit(操作码.Ldarg_0);
EmitCall(OpCodes.Call,typeof(ByteConverter).GetMethod(“EnumerateArray”),新的[]{typeof(byte[])};
il.Emit(操作码.Stloc,lbBytesEnumerator);
.......
il.Emit(操作码.Ldloc_S,lbBytesEnumerator);
EmitCall(OpCodes.Call,typeof(IEnumerator).GetProperty(“当前”).getMethod(),null);
LocalBuilder lbControlByte=il.DeclareLocal(propertyInfo.PropertyType);
il.Emit(opcode.Stloc,lbControlByte);
//枚举器下一步移动
il.Emit(操作码.Ldloc_S,lbBytesEnumerator);
EmitCall(OpCodes.Call,typeof(List.Enumerator).GetMethod(“MoveNext”),null);
发射(操作码Pop);
失败,原因是:

{“集合已修改;枚举操作可能无法执行。”}

变式2 当我按地址存储枚举数时(Ldloc\u S->Ldloca\u S)

。。。。。。
il.Emit(操作码.Ldloca_S,lbBytesEnumerator);
EmitCall(OpCodes.Call,typeof(IEnumerator).GetProperty(“当前”).getMethod(),null);
LocalBuilder lbControlByte=il.DeclareLocal(propertyInfo.PropertyType);
il.Emit(opcode.Stloc,lbControlByte);
它失败于:

{“试图读取或写入受保护的内存。这通常表示其他内存已损坏。”}

更新: Enumerate数组返回的枚举数不基于列表,但会产生以下结果:

        for (var i = 0; i < array.Length; i++)
            yield return array[i];
for(变量i=0;i
如果要调用代码,必须使用类型和方法信息,而不是类型生成器和方法生成器

因此,您需要创建类型(),然后使用该类型及其方法:

var generatedType = typeBuilder.CreateType();

var funcType = typeof(Func<,>).MakeGenericType(
generatedType, typeof(IEnumerable<string>));
var d = generatedType.GetMethod("MoveNext").CreateDelegate(funcType);
var generatedType=typeBuilder.CreateType();
var funcType=typeof(Func).MakeGenericType(
generatedType,typeof(IEnumerable));
var d=generatedType.GetMethod(“MoveNext”).CreateDelegate(funcType);
固定代码:

                // 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);
//控制字节
il.Emit(操作码.Ldloc,lbBytesEnumerator);
EmitCall(OpCodes.Callvirt,typeof(IEnumerator).GetProperty(“当前”).getMethod(),null);
LocalBuilder lbControlByte=il.DeclareLocal(propertyInfo.PropertyType);
il.Emit(opcode.Stloc,lbControlByte);
//枚举器下一步移动
il.Emit(操作码.Ldloc,lbBytesEnumerator);
EmitCall(OpCodes.Callvirt,typeof(IEnumerator.GetMethod(“MoveNext”),null);
发射(操作码Pop);

我怀疑第一个错误是因为您在调用
GetEnumerator
-之后修改了列表,在
指示的代码中,
如果您用C#编写代码,编译它,然后反汇编它会怎么样?也许这可以说明如何对其进行编码?@JonSkeet:Bit这将不同于其他地方使用的
IEnumerator
,而
lbBytesEnumerator
被声明为。(由于没有使用
CallVirt
,这可能会导致异常)。顺便说一句,除非你真的知道自己在做什么,否则通常需要使用
CallVirt
。@leppie:我敢说会的。我只是回答了你关于类型的问题:)
                // 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);