public void GenerateSave(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen> pushCtx, Action <IILGen> pushValue, Type valueType) { var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); var notnull = ilGenerator.DefineLabel(); var itemType = GetItemType(valueType); var localList = ilGenerator.DeclareLocal( typeof(IList <>).MakeGenericType(itemType)); var localIndex = ilGenerator.DeclareLocal(typeof(int)); var localCount = ilGenerator.DeclareLocal(typeof(int)); ilGenerator .Do(pushValue) .Castclass(localList.LocalType) .Stloc(localList) .Ldloc(localList) .BrtrueS(notnull) .Do(pushWriter) .Callvirt(() => default(AbstractBufferedWriter).WriteByteZero()) .Br(finish) .Mark(notnull) .Ldloc(localList) .Callvirt(localList.LocalType.GetInterface("ICollection`1").GetProperty("Count").GetGetMethod()) .Stloc(localCount) .Do(pushWriter) .Ldloc(localCount) .LdcI4(1) .Add() .Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0)) .LdcI4(0) .Stloc(localIndex) .Mark(next) .Ldloc(localIndex) .Ldloc(localCount) .BgeUn(finish); _itemDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloc(localList) .Ldloc(localIndex) .Callvirt(localList.LocalType.GetMethod("get_Item")), itemType); ilGenerator .Ldloc(localIndex) .LdcI4(1) .Add() .Stloc(localIndex) .Br(next) .Mark(finish); }
public void GenerateSave(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen> pushCtx, Action <IILGen> pushValue, Type valueType) { var itemType = GetItemType(valueType); var localValue = ilGenerator.DeclareLocal(valueType); var localHasValue = ilGenerator.DeclareLocal(typeof(bool)); var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushValue) .Stloc(localValue) .Do(pushWriter) .Ldloca(localValue) .Call(valueType.GetMethod("get_HasValue")) .Dup() .Stloc(localHasValue) .Callvirt(() => default(AbstractBufferedWriter).WriteBool(false)) .Ldloc(localHasValue) .Brfalse(finish); _itemDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localValue).Call(valueType.GetMethod("get_Value")), itemType); ilGenerator .Mark(finish); }
public void GenerateSave(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen> pushCtx, Action <IILGen> pushValue, Type saveType) { var notnull = ilGenerator.DefineLabel(); var completeFinish = ilGenerator.DefineLabel(); var notDictionary = ilGenerator.DefineLabel(); var keyType = saveType.GetGenericArguments()[0]; var valueType = saveType.GetGenericArguments()[1]; var typeAsIDictionary = typeof(IDictionary <,>).MakeGenericType(keyType, valueType); var typeAsICollection = typeAsIDictionary.GetInterface("ICollection`1"); var localDict = ilGenerator.DeclareLocal(typeAsIDictionary); ilGenerator .Do(pushValue) .Castclass(typeAsIDictionary) .Stloc(localDict) .Ldloc(localDict) .Brtrue(notnull) .Do(pushWriter) .Callvirt(() => default(AbstractBufferedWriter).WriteByteZero()) .Br(completeFinish) .Mark(notnull) .Do(pushWriter) .Ldloc(localDict) .Callvirt(typeAsICollection.GetProperty(nameof(ICollection.Count)).GetGetMethod()) .LdcI4(1) .Add() .Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0)); { var typeAsDictionary = typeof(Dictionary <,>).MakeGenericType(keyType, valueType); var getEnumeratorMethod = typeAsDictionary.GetMethods() .Single(m => m.Name == nameof(IEnumerable.GetEnumerator) && m.ReturnType.IsValueType && m.GetParameters().Length == 0); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty(nameof(IEnumerator.Current)).GetGetMethod(); var typeKeyValuePair = currentGetter.ReturnType; var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); var localPair = ilGenerator.DeclareLocal(typeKeyValuePair); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Ldloc(localDict) .Isinst(typeAsDictionary) .Brfalse(notDictionary) .Ldloc(localDict) .Castclass(typeAsDictionary) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloca(localEnumerator) .Call(typeAsIEnumerator.GetMethod(nameof(IEnumerator.MoveNext))) .Brfalse(finish) .Ldloca(localEnumerator) .Call(currentGetter) .Stloc(localPair); _keyDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()), keyType); _valueDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()), valueType); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloca(localEnumerator) .Constrained(typeAsIEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Br(completeFinish); } { var getEnumeratorMethod = typeAsIDictionary.GetInterface("IEnumerable`1").GetMethod(nameof(IEnumerable.GetEnumerator)); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty(nameof(IEnumerator.Current)).GetGetMethod(); var typeKeyValuePair = currentGetter.ReturnType; var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); var localPair = ilGenerator.DeclareLocal(typeKeyValuePair); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Mark(notDictionary) .Ldloc(localDict) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloc(localEnumerator) .Callvirt(() => default(IEnumerator).MoveNext()) .Brfalse(finish) .Ldloc(localEnumerator) .Callvirt(currentGetter) .Stloc(localPair); _keyDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()), keyType); _valueDescriptor.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloca(localPair).Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()), valueType); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloc(localEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Mark(completeFinish); } }