void SaveListPrefixBytes(uint secondaryKeyIndex, IILGen ilGenerator, string methodName, ParameterInfo[] methodParameters, IDictionary <string, MethodInfo> apartFields) { var writerLoc = ilGenerator.DeclareLocal(typeof(ByteBufferWriter)); ilGenerator .Newobj(() => new ByteBufferWriter()) .Stloc(writerLoc); Action <IILGen> pushWriter = il => il.Ldloc(writerLoc); WriteShortPrefixIl(ilGenerator, pushWriter, ObjectDB.AllRelationsSKPrefix); //ByteBuffered.WriteVUInt32(RelationInfo.Id); WriteIdIl(ilGenerator, pushWriter, (int)_relationInfo.Id); //ByteBuffered.WriteVUInt32(skIndex); WriteIdIl(ilGenerator, pushWriter, (int)secondaryKeyIndex); var secondaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetSecondaryKeyFields(secondaryKeyIndex); var paramCount = methodParameters.Length - 1; //last param is key proposition SaveMethodParameters(ilGenerator, methodName, methodParameters, paramCount, apartFields, secondaryKeyFields, writerLoc); var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); }
void CreateMethodContains(IILGen ilGenerator, Type relationDBManipulatorType, ParameterInfo[] methodParameters, IDictionary <string, MethodInfo> apartFields, Action <IILGen> pushWriter, IILLocal writerLoc) { //ByteBufferWriter.WriteVUInt32(RelationInfo.Id); WriteIdIl(ilGenerator, pushWriter, (int)_relationInfo.Id); var primaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetPrimaryKeyFields(); var count = SaveMethodParameters(ilGenerator, "Contains", methodParameters, methodParameters.Length, apartFields, primaryKeyFields, writerLoc); if (count != primaryKeyFields.Count) { throw new BTDBException($"Number of parameters in Contains does not match primary key count {primaryKeyFields.Count}."); } //call manipulator.Contains ilGenerator .Ldarg(0); //manipulator //call byteBuffer.data var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("Contains")); }
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); }
void CreateMethodFindById(IILGen ilGenerator, Type relationDBManipulatorType, string methodName, ParameterInfo[] methodParameters, Type methodReturnType, IDictionary <string, MethodInfo> apartFields, Action <IILGen> pushWriter, IILLocal writerLoc) { var isPrefixBased = ReturnsEnumerableOfClientType(methodReturnType, _relationInfo.ClientType); if (isPrefixBased) { WriteShortPrefixIl(ilGenerator, pushWriter, _relationInfo.Prefix); } else { WriteShortPrefixIl(ilGenerator, pushWriter, ObjectDB.AllRelationsPKPrefix); //ByteBufferWriter.WriteVUInt32(RelationInfo.Id); WriteIdIl(ilGenerator, pushWriter, (int)_relationInfo.Id); } var primaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetPrimaryKeyFields(); var count = SaveMethodParameters(ilGenerator, methodName, methodParameters, methodParameters.Length, apartFields, primaryKeyFields, writerLoc); if (!isPrefixBased && count != primaryKeyFields.Count) { throw new BTDBException( $"Number of parameters in {methodName} does not match primary key count {primaryKeyFields.Count}."); } //call manipulator.FindBy_ ilGenerator .Ldarg(0); //manipulator //call byteBuffer.data var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Call(dataGetter); if (isPrefixBased) { ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("FindByPrimaryKeyPrefix")); } else { ilGenerator.LdcI4(ShouldThrowWhenKeyNotFound(methodName, methodReturnType) ? 1 : 0); ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("FindByIdOrDefault")); if (methodReturnType == typeof(void)) { ilGenerator.Pop(); } } }
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); }
void CreateMethodFindBy(IILGen ilGenerator, Type relationDBManipulatorType, string methodName, ParameterInfo[] methodParameters, Type methodReturnType, IDictionary <string, MethodInfo> apartFields, Action <IILGen> pushWriter, IILLocal writerLoc) { bool allowDefault = false; var skName = methodName.Substring(6); if (skName.EndsWith("OrDefault")) { skName = skName.Substring(0, skName.Length - 9); allowDefault = true; } WriteShortPrefixIl(ilGenerator, pushWriter, ObjectDB.AllRelationsSKPrefix); var skIndex = _relationInfo.ClientRelationVersionInfo.GetSecondaryKeyIndex(skName); //ByteBuffered.WriteVUInt32(RelationInfo.Id); WriteIdIl(ilGenerator, pushWriter, (int)_relationInfo.Id); //ByteBuffered.WriteVUInt32(skIndex); WriteIdIl(ilGenerator, pushWriter, (int)skIndex); var secondaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetSecondaryKeyFields(skIndex); SaveMethodParameters(ilGenerator, methodName, methodParameters, methodParameters.Length, apartFields, secondaryKeyFields, writerLoc); //call public T FindBySecondaryKeyOrDefault(uint secondaryKeyIndex, uint prefixParametersCount, ByteBuffer secKeyBytes, bool throwWhenNotFound) ilGenerator.Ldarg(0); //manipulator ilGenerator.LdcI4((int)skIndex); ilGenerator.LdcI4(methodParameters.Length + apartFields.Count); //call byteBuffer.data var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); if (ReturnsEnumerableOfClientType(methodReturnType, _relationInfo.ClientType)) { ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("FindBySecondaryKey")); } else { ilGenerator.LdcI4(allowDefault ? 0 : 1); //? should throw ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("FindBySecondaryKeyOrDefault")); } }
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); }
void CreateMethodListById(IILGen ilGenerator, Type relationDBManipulatorType, string methodName, ParameterInfo[] methodParameters, IDictionary <string, MethodInfo> apartFields, Action <IILGen> pushWriter, IILLocal writerLoc) { WriteShortPrefixIl(ilGenerator, pushWriter, _relationInfo.Prefix); var primaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetPrimaryKeyFields(); var paramsCount = SaveMethodParameters(ilGenerator, methodName, methodParameters, methodParameters.Length, apartFields, primaryKeyFields, writerLoc); //call manipulator.GetEnumerator(tr, byteBuffer) ilGenerator .Ldarg(0); //manipulator //call byteBuffer.data var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); ilGenerator.LdcI4(paramsCount + apartFields.Count); ilGenerator.Callvirt(relationDBManipulatorType.GetMethod(methodName)); }
void SavePKListPrefixBytes(IILGen ilGenerator, string methodName, ParameterInfo[] methodParameters, IDictionary <string, MethodInfo> apartFields) { var writerLoc = ilGenerator.DeclareLocal(typeof(ByteBufferWriter)); ilGenerator .Newobj(() => new ByteBufferWriter()) .Stloc(writerLoc); Action <IILGen> pushWriter = il => il.Ldloc(writerLoc); WriteShortPrefixIl(ilGenerator, pushWriter, _relationInfo.Prefix); var keyFields = _relationInfo.ClientRelationVersionInfo.GetPrimaryKeyFields(); var paramCount = methodParameters.Length - 1; //last param is key proposition SaveMethodParameters(ilGenerator, methodName, methodParameters, paramCount, apartFields, keyFields, writerLoc); var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); }
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 GenerateLoad(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx, Action <IILGen> pushDescriptor, Type targetType) { if (targetType == typeof(object)) { var resultLoc = ilGenerator.DeclareLocal(typeof(DynamicObject), "result"); var labelNoCtx = ilGenerator.DefineLabel(); ilGenerator .Do(pushDescriptor) .Castclass(typeof(ObjectTypeDescriptor)) .Newobj(typeof(DynamicObject).GetConstructor(new[] { typeof(ObjectTypeDescriptor) })) .Stloc(resultLoc) .Do(pushCtx) .BrfalseS(labelNoCtx) .Do(pushCtx) .Ldloc(resultLoc) .Callvirt(() => default(ITypeBinaryDeserializerContext).AddBackRef(null)) .Mark(labelNoCtx); var idx = 0; foreach (var pair in _fields) { var idxForCapture = idx; ilGenerator.Ldloc(resultLoc); ilGenerator.LdcI4(idx); pair.Value.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor) .LdcI4(idxForCapture) .Callvirt(() => default(ITypeDescriptor).NestedType(0)), typeof(object), _typeSerializers.ConvertorGenerator); ilGenerator.Callvirt(() => default(DynamicObject).SetFieldByIdxFast(0, null)); idx++; } ilGenerator .Ldloc(resultLoc) .Castclass(typeof(object)); } else { var resultLoc = ilGenerator.DeclareLocal(targetType, "result"); var labelNoCtx = ilGenerator.DefineLabel(); ilGenerator .Newobj(targetType.GetConstructor(Type.EmptyTypes)) .Stloc(resultLoc) .Do(pushCtx) .BrfalseS(labelNoCtx) .Do(pushCtx) .Ldloc(resultLoc) .Callvirt(() => default(ITypeBinaryDeserializerContext).AddBackRef(null)) .Mark(labelNoCtx); var props = targetType.GetProperties(); for (var idx = 0; idx < _fields.Count; idx++) { var idxForCapture = idx; var pair = _fields[idx]; var prop = props.FirstOrDefault(p => GetPersitentName(p) == pair.Key); if (prop == null || !_typeSerializers.IsSafeToLoad(prop.PropertyType)) { pair.Value.GenerateSkipEx(ilGenerator, pushReader, pushCtx); continue; } ilGenerator.Ldloc(resultLoc); pair.Value.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(idxForCapture).Callvirt(() => default(ITypeDescriptor).NestedType(0)), prop.PropertyType, _typeSerializers.ConvertorGenerator); ilGenerator.Callvirt(prop.GetSetMethod()); } ilGenerator.Ldloc(resultLoc); } }
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) .Dup() .Stloc(localList) .BrtrueS(notnull) .Do(pushWriter) .LdcI4(0) .Callvirt(() => default(AbstractBufferedWriter).WriteVUInt32(0)) .Br(finish) .Mark(notnull) .Ldloc(localList) .Callvirt(localList.LocalType.GetInterface("ICollection`1").GetProperty("Count").GetGetMethod()) .Stloc(localCount) .Do(pushWriter) .Ldloc(localCount) .LdcI4(1) .Add() .ConvU4() .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 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 GenerateLoad(IILGen ilGenerator, Action<IILGen> pushReader, Action<IILGen> pushCtx, Action<IILGen> pushDescriptor, Type targetType) { if (targetType == typeof(object)) { var resultLoc = ilGenerator.DeclareLocal(typeof(DynamicObject), "result"); var labelNoCtx = ilGenerator.DefineLabel(); ilGenerator .Do(pushDescriptor) .Castclass(typeof(ObjectTypeDescriptor)) .Newobj(typeof(DynamicObject).GetConstructor(new[] { typeof(ObjectTypeDescriptor) })) .Stloc(resultLoc) .Do(pushCtx) .BrfalseS(labelNoCtx) .Do(pushCtx) .Ldloc(resultLoc) .Callvirt(() => default(ITypeBinaryDeserializerContext).AddBackRef(null)) .Mark(labelNoCtx); var idx = 0; foreach (var pair in _fields) { var idxForCapture = idx; ilGenerator.Ldloc(resultLoc); ilGenerator.LdcI4(idx); pair.Value.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor) .LdcI4(idxForCapture) .Callvirt(() => default(ITypeDescriptor).NestedType(0)), typeof(object), _typeSerializers.ConvertorGenerator); ilGenerator.Callvirt(() => default(DynamicObject).SetFieldByIdxFast(0, null)); idx++; } ilGenerator .Ldloc(resultLoc) .Castclass(typeof(object)); } else { var resultLoc = ilGenerator.DeclareLocal(targetType, "result"); var labelNoCtx = ilGenerator.DefineLabel(); ilGenerator .Newobj(targetType.GetConstructor(Type.EmptyTypes)) .Stloc(resultLoc) .Do(pushCtx) .BrfalseS(labelNoCtx) .Do(pushCtx) .Ldloc(resultLoc) .Callvirt(() => default(ITypeBinaryDeserializerContext).AddBackRef(null)) .Mark(labelNoCtx); var props = targetType.GetProperties(); for (var idx = 0; idx < _fields.Count; idx++) { var idxForCapture = idx; var pair = _fields[idx]; var prop = props.FirstOrDefault(p => GetPersitentName(p) == pair.Key); if (prop == null || !_typeSerializers.IsSafeToLoad(prop.PropertyType)) { pair.Value.GenerateSkipEx(ilGenerator, pushReader, pushCtx); continue; } ilGenerator.Ldloc(resultLoc); pair.Value.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(idxForCapture).Callvirt(() => default(ITypeDescriptor).NestedType(0)), prop.PropertyType, _typeSerializers.ConvertorGenerator); ilGenerator.Callvirt(prop.GetSetMethod()); } ilGenerator.Ldloc(resultLoc); } }
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 .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); }