Question

Please advise how can I build call of property Current and MoveNext of IEnumerable<byte>.

Target

I'd like to get something like:

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

Variant 1

Here is code:

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);

Failed with:

{"Collection was modified; enumeration operation may not execute."}

Variant 2

And when I store enumerator by address (Ldloc_S -> Ldloca_S)

......
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);

It fails with:

{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}

Update:

Enumerate array returns Enumerator based not on List but it's yielding results:

        for (var i = 0; i < array.Length; i++)
            yield return array[i];
Was it helpful?

Solution 2

Fixed code:

                // 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);

OTHER TIPS

If you want to invoke your code, you have to work with Types and MethodInfos, not TypeBuilders and MethodBuilders.

So, you need to CreateType() and then use that Type and its method:

var generatedType = typeBuilder.CreateType();

var funcType = typeof(Func<,>).MakeGenericType(
generatedType, typeof(IEnumerable<string>));
var d = generatedType.GetMethod("MoveNext").CreateDelegate(funcType);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top