public void Save(IILGen ilGenerator, Action <IILGen> pushWriterOrCtx, Action <IILGen> pushValue) { var realFinish = ilGenerator.DefineLabel(); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); var localValue = ilGenerator.DeclareLocal(_type !); var typeAsICollection = _type.GetInterface("ICollection`1"); var typeAsIEnumerable = _type.GetInterface("IEnumerable`1"); var getEnumeratorMethod = typeAsIEnumerable !.GetMethod("GetEnumerator"); var typeAsIEnumerator = getEnumeratorMethod !.ReturnType; var typeKeyValuePair = typeAsICollection !.GetGenericArguments()[0]; var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); var localPair = ilGenerator.DeclareLocal(typeKeyValuePair); ilGenerator .Do(pushValue) .Stloc(localValue) .Do(pushWriterOrCtx) .Ldloc(localValue) .Castclass(typeof(object)) .Callvirt(() => default(IWriterCtx).WriteObject(null)) .Brfalse(realFinish) .Do(Extensions.PushWriterFromCtx(pushWriterOrCtx)) .Ldloc(localValue) .Callvirt(typeAsICollection.GetProperty("Count") !.GetGetMethod() !) .ConvU4() .Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0)) .Ldloc(localValue) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloc(localEnumerator) .Callvirt(() => default(IEnumerator).MoveNext()) .Brfalse(finish) .Ldloc(localEnumerator) .Callvirt(typeAsIEnumerator.GetProperty("Current") !.GetGetMethod() !) .Stloc(localPair); var keyAndValueTypes = _type.GetGenericArguments(); _keysHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _keysHandler.NeedsCtx()), il => il .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Key") !.GetGetMethod() !) .Do(_typeConvertGenerator.GenerateConversion(keyAndValueTypes[0], _keysHandler.HandledType()) !)); _valuesHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _valuesHandler.NeedsCtx()), il => il .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Value") !.GetGetMethod() !) .Do(_typeConvertGenerator.GenerateConversion(keyAndValueTypes[1], _valuesHandler.HandledType()) !)); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloc(localEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Mark(realFinish); }
public void Save(IILGen ilGenerator, Action <IILGen> pushWriterOrCtx, Action <IILGen> pushValue) { var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); var localValue = ilGenerator.DeclareLocal(_type); var localIndex = ilGenerator.DeclareLocal(typeof(int)); var localCount = ilGenerator.DeclareLocal(typeof(int)); ilGenerator .LdcI4(0) .Stloc(localIndex) .Do(pushValue) .Stloc(localValue) .Do(pushWriterOrCtx) .Ldloc(localValue) .Castclass(typeof(object)) .Callvirt(() => default(IWriterCtx).WriteObject(null)) .Brfalse(finish) .Ldloc(localValue) .Callvirt(_type.GetInterface("ICollection`1").GetProperty("Count").GetGetMethod()) .Stloc(localCount) .Do(Extensions.PushWriterFromCtx(pushWriterOrCtx)) .Ldloc(localCount) .ConvU4() .Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0)) .Mark(next) .Ldloc(localIndex) .Ldloc(localCount) .BgeUn(finish); _itemsHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _itemsHandler.NeedsCtx()), il => il .Ldloc(localValue) .Ldloc(localIndex) .Callvirt(_type.GetMethod("get_Item")) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[0], _itemsHandler.HandledType()))); ilGenerator .Ldloc(localIndex) .LdcI4(1) .Add() .Stloc(localIndex) .Br(next) .Mark(finish); }