internal static void FillBufferWhenNotIgnoredKeyPropositionIl(ushort advEnumParamOrder, TableFieldInfo field, IILLocal emptyBufferLoc, FieldInfo instField, IILGen ilGenerator) { //stack contains KeyProposition var ignoreLabel = ilGenerator.DefineLabel(instField + "_ignore"); var doneLabel = ilGenerator.DefineLabel(instField + "_done"); var writerLoc = ilGenerator.DeclareLocal(typeof(AbstractBufferedWriter)); ilGenerator .Dup() .LdcI4((int)KeyProposition.Ignored) .BeqS(ignoreLabel) .Newobj(() => new ByteBufferWriter()) .Stloc(writerLoc); field.Handler.Save(ilGenerator, il => il.Ldloc(writerLoc), il => il.Ldarg(advEnumParamOrder).Ldfld(instField)); var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); ilGenerator .Br(doneLabel) .Mark(ignoreLabel) .Ldloc(emptyBufferLoc) .Mark(doneLabel); }
public void GenerateSkip(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx) { var localCount = ilGenerator.DeclareLocal(typeof(uint)); var skipFinished = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .Stloc(localCount) .Ldloc(localCount) .Brfalse(skipFinished) .Mark(next) .Ldloc(localCount) .LdcI4(1) .Sub() .Stloc(localCount) .Ldloc(localCount) .Brfalse(skipFinished); _keyDescriptor.GenerateSkipEx(ilGenerator, pushReader, pushCtx); _valueDescriptor.GenerateSkipEx(ilGenerator, pushReader, pushCtx); ilGenerator .Br(next) .Mark(skipFinished); }
public void Save(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen> pushCtx, 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(pushCtx) .Do(pushWriter) .Ldloc(localValue) .Castclass(typeof(object)) .Callvirt(typeof(IWriterCtx).GetMethod(nameof(IWriterCtx.WriteObject)) !) .Brfalse(realFinish) .Do(pushWriter) .Ldloc(localValue) .Callvirt(typeAsICollection.GetProperty("Count") !.GetGetMethod() !) .ConvU4() .Call(typeof(SpanWriter).GetMethod(nameof(SpanWriter.WriteVUInt32)) !) .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, pushWriter, pushCtx, il => il .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Key") !.GetGetMethod() !) .Do(_typeConvertGenerator.GenerateConversion(keyAndValueTypes[0], _keysHandler.HandledType()) !)); _valuesHandler.Save(ilGenerator, pushWriter, pushCtx, 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 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); _keysHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _keysHandler.NeedsCtx()), il => il .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[0], _keysHandler.HandledType()))); _valuesHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _valuesHandler.NeedsCtx()), il => il .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[1], _valuesHandler.HandledType()))); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloc(localEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Mark(realfinish); }
public void GenerateLoad(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx, Action <IILGen> pushDescriptor, Type targetType) { var genericArguments = targetType.GetGenericArguments(); var itemType = genericArguments.Length > 0 ? targetType.GetGenericArguments()[0] : typeof(object); if (itemType == typeof(object)) { var noValue = ilGenerator.DefineLabel(); var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadBool()) .Brfalse(noValue); _itemDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(0).Callvirt(() => default(ITypeDescriptor).NestedType(0)), typeof(object), _convertorGenerator); ilGenerator .Br(finish) .Mark(noValue) .Ldnull() .Mark(finish); } else { var localResult = ilGenerator.DeclareLocal(targetType); var finish = ilGenerator.DefineLabel(); var noValue = ilGenerator.DefineLabel(); var nullableType = typeof(Nullable <>).MakeGenericType(itemType); if (!targetType.IsAssignableFrom(nullableType)) { throw new NotSupportedException(); } ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadBool()) .Brfalse(noValue); _itemDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(0).Callvirt(() => default(ITypeDescriptor).NestedType(0)), itemType, _convertorGenerator); ilGenerator .Newobj(nullableType.GetConstructor(new[] { itemType })) .Stloc(localResult) .BrS(finish) .Mark(noValue) .Ldloca(localResult) .InitObj(nullableType) .Mark(finish) .Ldloc(localResult); } }
public void GenerateTypeIterator(IILGen ilGenerator, Action<IILGen> pushObj, Action<IILGen> pushCtx, Type type) { var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); var keyType = _owner._typeSerializers.LoadAsType(_owner._keyDescriptor); var valueType = _owner._typeSerializers.LoadAsType(_owner._valueDescriptor); if (_owner._type == null) _owner._type = type; var isDict = _owner._type != null && _owner._type.GetGenericTypeDefinition() == typeof(Dictionary<,>); var typeAsIDictionary = isDict ? _owner._type : typeof(IDictionary<,>).MakeGenericType(keyType, valueType); var getEnumeratorMethod = isDict ? typeAsIDictionary.GetMethods() .Single( m => m.Name == "GetEnumerator" && m.ReturnType.IsValueType && m.GetParameters().Length == 0) : typeAsIDictionary.GetInterface("IEnumerable`1").GetMethod("GetEnumerator"); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty("Current").GetGetMethod(); var typeKeyValuePair = currentGetter.ReturnType; var localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); var localPair = ilGenerator.DeclareLocal(typeKeyValuePair); ilGenerator .Do(pushObj) .Castclass(typeAsIDictionary) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Do(il => { if (isDict) { il .Ldloca(localEnumerator) .Call(typeAsIEnumerator.GetMethod("MoveNext")); } else { il .Ldloc(localEnumerator) .Callvirt(() => default(IEnumerator).MoveNext()); } }) .Brfalse(finish) .Do(il => { if (isDict) { il .Ldloca(localEnumerator) .Call(currentGetter); } else { il .Ldloc(localEnumerator) .Callvirt(currentGetter); } }) .Stloc(localPair); if (!_owner._keyDescriptor.Sealed) { ilGenerator .Do(pushCtx) .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)); } if (!_owner._valueDescriptor.Sealed) { ilGenerator .Do(pushCtx) .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)); } ilGenerator .Br(next) .Mark(finish) .Finally() .Do(il => { if (isDict) { il .Ldloca(localEnumerator) .Constrained(typeAsIEnumerator); } else { il.Ldloc(localEnumerator); } }) .Callvirt(() => default(IDisposable).Dispose()) .EndTry(); }
public void GenerateSkip(IILGen ilGenerator, Action<IILGen> pushReader, Action<IILGen> pushCtx) { var localCount = ilGenerator.DeclareLocal(typeof(uint)); var skipFinished = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .Stloc(localCount) .Ldloc(localCount) .Brfalse(skipFinished) .Mark(next) .Ldloc(localCount) .LdcI4(1) .Sub() .Stloc(localCount) .Ldloc(localCount) .Brfalse(skipFinished); _keyDescriptor.GenerateSkipEx(ilGenerator, pushReader, pushCtx); _valueDescriptor.GenerateSkipEx(ilGenerator, pushReader, pushCtx); ilGenerator .Br(next) .Mark(skipFinished); }
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("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 == "GetEnumerator" && m.ReturnType.IsValueType && m.GetParameters().Length == 0); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty("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) .Castclass(typeAsDictionary) .Brfalse(notDictionary) .Ldloc(localDict) .Castclass(typeAsDictionary) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloca(localEnumerator) .Call(typeAsIEnumerator.GetMethod("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("GetEnumerator"); var typeAsIEnumerator = getEnumeratorMethod.ReturnType; var currentGetter = typeAsIEnumerator.GetProperty("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); } }
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); } }
public void GenerateTypeIterator(IILGen ilGenerator, Action <IILGen> pushObj, Action <IILGen> pushCtx, Type type) { var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); if (type == typeof(object)) { type = _owner.GetPreferedType(); } var targetIDictionary = _owner.GetInterface(type); var targetTypeArguments = targetIDictionary.GetGenericArguments(); var keyType = _owner._typeSerializers.LoadAsType(_owner._keyDescriptor, targetTypeArguments[0]); var valueType = _owner._typeSerializers.LoadAsType(_owner._valueDescriptor, targetTypeArguments[1]); if (_owner._type == null) { _owner._type = type; } var isDict = type.GetGenericTypeDefinition() == typeof(Dictionary <,>); var typeAsIDictionary = isDict ? type : typeof(IDictionary <,>).MakeGenericType(keyType, valueType); var getEnumeratorMethod = isDict ? typeAsIDictionary.GetMethods() .Single( m => m.Name == nameof(IEnumerable.GetEnumerator) && m.ReturnType.IsValueType && m.GetParameters().Length == 0) : 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); ilGenerator .Do(pushObj) .Castclass(typeAsIDictionary) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Do(il => { if (isDict) { il .Ldloca(localEnumerator) .Call(typeAsIEnumerator.GetMethod(nameof(IEnumerator.MoveNext))); } else { il .Ldloc(localEnumerator) .Callvirt(() => default(IEnumerator).MoveNext()); } }) .Brfalse(finish) .Do(il => { if (isDict) { il .Ldloca(localEnumerator) .Call(currentGetter); } else { il .Ldloc(localEnumerator) .Callvirt(currentGetter); } }) .Stloc(localPair); if (!_owner._keyDescriptor.Sealed) { ilGenerator .Do(pushCtx) .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)); } if (!_owner._valueDescriptor.Sealed) { ilGenerator .Do(pushCtx) .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)); } ilGenerator .Br(next) .Mark(finish) .Finally() .Do(il => { if (isDict) { il .Ldloca(localEnumerator) .Constrained(typeAsIEnumerator); } else { il.Ldloc(localEnumerator); } }) .Callvirt(() => default(IDisposable).Dispose()) .EndTry(); }
public void GenerateTypeIterator(IILGen ilGenerator, Action<IILGen> pushObj, Action<IILGen> pushCtx) { var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); var keyType = _owner._typeSerializers.LoadAsType(_owner._keyDescriptor); var valueType = _owner._typeSerializers.LoadAsType(_owner._valueDescriptor); var typeAsIDictionary = typeof(IDictionary<,>).MakeGenericType(keyType, valueType); var typeAsICollection = typeAsIDictionary.GetInterface("ICollection`1"); var typeAsIEnumerable = typeAsIDictionary.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(pushObj) .Castclass(typeAsIDictionary) .Callvirt(getEnumeratorMethod) .Stloc(localEnumerator) .Try() .Mark(next) .Ldloc(localEnumerator) .Callvirt(() => default(IEnumerator).MoveNext()) .Brfalse(finish) .Ldloc(localEnumerator) .Callvirt(typeAsIEnumerator.GetProperty("Current").GetGetMethod()) .Stloc(localPair); if (!_owner._keyDescriptor.Sealed) { ilGenerator .Do(pushCtx) .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)); } if (!_owner._valueDescriptor.Sealed) { ilGenerator .Do(pushCtx) .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)); } ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloc(localEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry(); }
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); _keysHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _keysHandler.NeedsCtx()), il => il .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Key").GetGetMethod()) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[0], _keysHandler.HandledType()))); _valuesHandler.Save(ilGenerator, Extensions.PushWriterOrCtxAsNeeded(pushWriterOrCtx, _valuesHandler.NeedsCtx()), il => il .Ldloca(localPair) .Call(typeKeyValuePair.GetProperty("Value").GetGetMethod()) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[1], _valuesHandler.HandledType()))); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloc(localEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Mark(realfinish); }