public void Load(IILGen ilGenerator, Action<IILGen> pushReaderOrCtx) { var localCount = ilGenerator.DeclareLocal(typeof(uint)); var localResultOfObject = ilGenerator.DeclareLocal(typeof(object)); var localResult = ilGenerator.DeclareLocal(HandledType()); var loadSkipped = ilGenerator.DefineLabel(); var finish = ilGenerator.DefineLabel(); var readfinish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); var genericArguments = _type.GetGenericArguments(); object fake; ilGenerator .Do(pushReaderOrCtx) .Ldloca(localResultOfObject) .Callvirt(() => default(IReaderCtx).ReadObject(out fake)) .Brfalse(loadSkipped) .Do(Extensions.PushReaderFromCtx(pushReaderOrCtx)) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .Stloc(localCount) .Ldloc(localCount) .Newobj(typeof(Dictionary<,>).MakeGenericType(genericArguments).GetConstructor(new[] { typeof(int) })) .Stloc(localResult) .Do(pushReaderOrCtx) .Ldloc(localResult) .Castclass(typeof(object)) .Callvirt(() => default(IReaderCtx).RegisterObject(null)) .Mark(next) .Ldloc(localCount) .Brfalse(readfinish) .Ldloc(localCount) .LdcI4(1) .Sub() .ConvU4() .Stloc(localCount) .Ldloc(localResult) .GenerateLoad(_keysHandler, genericArguments[0], pushReaderOrCtx, _typeConvertorGenerator) .GenerateLoad(_valuesHandler, genericArguments[1], pushReaderOrCtx, _typeConvertorGenerator) .Callvirt(_type.GetMethod("Add")) .Br(next) .Mark(readfinish) .Do(pushReaderOrCtx) .Callvirt(() => default(IReaderCtx).ReadObjectDone()) .Br(finish) .Mark(loadSkipped) .Ldloc(localResultOfObject) .Isinst(_type) .Stloc(localResult) .Mark(finish) .Ldloc(localResult); }
public bool FreeContent(IILGen ilGenerator, Action<IILGen> pushReaderOrCtx) { var needsFreeContent = false; var localCount = ilGenerator.DeclareLocal(typeof(uint)); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReaderOrCtx) .Callvirt(() => ((IReaderCtx)null).SkipObject()) .Brfalse(finish) .Do(Extensions.PushReaderFromCtx(pushReaderOrCtx)) .Callvirt(() => ((AbstractBufferedReader)null).ReadVUInt32()) .Stloc(localCount) .Mark(next) .Ldloc(localCount) .Brfalse(finish) .Ldloc(localCount) .LdcI4(1) .Sub() .ConvU4() .Stloc(localCount) .GenerateFreeContent(_keysHandler, pushReaderOrCtx, ref needsFreeContent) .GenerateFreeContent(_valuesHandler, pushReaderOrCtx, ref needsFreeContent) .Br(next) .Mark(finish); return needsFreeContent; }
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 GenerateLoad(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx, Action <IILGen> pushDescriptor, Type targetType) { var localCount = ilGenerator.DeclareLocal(typeof(int)); var targetIDictionary = targetType.GetInterface("IDictionary`2") ?? targetType; var targetTypeArguments = targetIDictionary.GetGenericArguments(); var keyType = _typeSerializers.LoadAsType(_keyDescriptor, targetTypeArguments[0]); var valueType = _typeSerializers.LoadAsType(_valueDescriptor, targetTypeArguments[1]); var dictionaryType = typeof(DictionaryWithDescriptor <,>).MakeGenericType(keyType, valueType); if (!targetType.IsAssignableFrom(dictionaryType)) { throw new InvalidOperationException(); } var localDict = ilGenerator.DeclareLocal(dictionaryType); var loadFinished = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .ConvI4() .Dup() .LdcI4(1) .Sub() .Stloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .Do(pushDescriptor) .Newobj(dictionaryType.GetConstructor(new[] { typeof(int), typeof(ITypeDescriptor) })) .Stloc(localDict) .Mark(next) .Ldloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Stloc(localCount) .Ldloc(localDict); _keyDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(0).Callvirt(() => default(ITypeDescriptor).NestedType(0)), keyType, _convertorGenerator); _valueDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(1).Callvirt(() => default(ITypeDescriptor).NestedType(0)), valueType, _convertorGenerator); ilGenerator .Callvirt(dictionaryType.GetMethod("Add")) .Br(next) .Mark(loadFinished) .Ldloc(localDict) .Castclass(targetType); }
public void GenerateLoad(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx, Action <IILGen> pushDescriptor, Type targetType) { var localCount = ilGenerator.DeclareLocal(typeof(int)); var itemType = _typeSerializers.LoadAsType(_itemDescriptor); var listType = typeof(ListWithDescriptor <>).MakeGenericType(itemType); if (!targetType.IsAssignableFrom(listType)) { throw new NotSupportedException(); } var localList = ilGenerator.DeclareLocal(listType); var loadFinished = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .ConvI4() .Dup() .Stloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Dup() .Stloc(localCount) .Do(pushDescriptor) .Newobj(listType.GetConstructor(new[] { typeof(int), typeof(ITypeDescriptor) })) .Stloc(localList) .Mark(next) .Ldloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Stloc(localCount) .Ldloc(localList); _itemDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(0).Callvirt(() => default(ITypeDescriptor).NestedType(0)), itemType, _convertorGenerator); ilGenerator .Callvirt(listType.GetInterface("ICollection`1").GetMethod("Add")) .Br(next) .Mark(loadFinished) .Ldloc(localList) .Castclass(targetType); }
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); }
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 = _listTypeDescriptor.GetPreferedType(); } var targetIList = type.GetInterface("IList`1") ?? type; var targetTypeArguments = targetIList.GetGenericArguments(); var itemType = _listTypeDescriptor._typeSerializers.LoadAsType(_listTypeDescriptor._itemDescriptor, targetTypeArguments[0]); var localList = ilGenerator.DeclareLocal(typeof(IList <>).MakeGenericType(itemType)); var localIndex = ilGenerator.DeclareLocal(typeof(int)); var localCount = ilGenerator.DeclareLocal(typeof(int)); ilGenerator .Do(pushObj) .Castclass(localList.LocalType) .Stloc(localList) .Ldloc(localList) .Callvirt(localList.LocalType.GetInterface("ICollection`1").GetProperty("Count").GetGetMethod()) .Stloc(localCount) .LdcI4(0) .Stloc(localIndex) .Mark(next) .Ldloc(localIndex) .Ldloc(localCount) .BgeUn(finish) .Do(pushCtx) .Ldloc(localList) .Ldloc(localIndex) .Callvirt(localList.LocalType.GetMethod("get_Item")) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)) .Ldloc(localIndex) .LdcI4(1) .Add() .Stloc(localIndex) .Br(next) .Mark(finish); }
MemorizedPositionWithLength SkipWithMemorizing(int activeBuffer, IILGen ilGenerator, Action <IILGen> pushReader, IFieldHandler handler, IILLocal tempPosition) { var memoPos = ilGenerator.DeclareLocal(typeof(IMemorizedPosition)); var memoLen = ilGenerator.DeclareLocal(typeof(int)); var position = new MemorizedPositionWithLength { BufferIndex = activeBuffer, Pos = memoPos, Length = memoLen }; MemorizeCurrentPosition(ilGenerator, pushReader, memoPos); StoreCurrentPosition(ilGenerator, pushReader, tempPosition); handler.Skip(ilGenerator, pushReader); ilGenerator .Do(pushReader) //[VR] .Callvirt(() => default(ByteArrayReader).GetCurrentPosition()) //[posNew]; .Ldloc(tempPosition) //[posNew, posOld] .Sub() //[readLen] .ConvI4() //[readLen(i)] .Stloc(memoLen); //[] return(position); }
void CreateSaverIl(IILGen ilGen, IEnumerable <TableFieldInfo> fields, Action <IILGen> pushInstance, Action <IILGen> pushRelationIface, Action <IILGen> pushWriter, Action <IILGen> pushTransaction) { var anyNeedsCtx = fields.Any(tfi => tfi.Handler.NeedsCtx()); IILLocal writerCtxLocal = null; if (anyNeedsCtx) { writerCtxLocal = ilGen.DeclareLocal(typeof(IWriterCtx)); ilGen .Do(pushTransaction) .Do(pushWriter) .Newobj(() => new DBWriterCtx(null, null)) .Stloc(writerCtxLocal); } var props = ClientType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var field in fields) { var getter = props.First(p => GetPersistentName(p) == field.Name).GetGetMethod(true); Action <IILGen> writerOrCtx; var handler = field.Handler.SpecializeSaveForType(getter.ReturnType); if (handler.NeedsCtx()) { writerOrCtx = il => il.Ldloc(writerCtxLocal); } else { writerOrCtx = pushWriter; } MethodInfo apartFieldGetter = null; if (pushRelationIface != null) { ApartFields.TryGetValue(field.Name, out apartFieldGetter); } handler.Save(ilGen, writerOrCtx, il => { if (apartFieldGetter != null) { il.Do(pushRelationIface); getter = apartFieldGetter; } else { il.Do(pushInstance); } il.Callvirt(getter); _relationInfoResolver.TypeConvertorGenerator.GenerateConversion(getter.ReturnType, handler.HandledType())(il); }); } }
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); } }
static void MergerInitializeBufferReader(IILGen ilGenerator, ref BufferInfo bi, ushort arg) { if (bi.ReaderCreated) { return; } bi.ReaderCreated = true; var readerLoc = ilGenerator.DeclareLocal(typeof(ByteArrayReader)); bi.PushReader = il => il.Ldloc(readerLoc); ilGenerator .Ldarg(arg) .Newobj(() => new ByteArrayReader(null)) .Stloc(readerLoc); }
public void Save(IILGen ilGenerator, Action <IILGen> pushWriterOrCtx, Action <IILGen> pushValue) { var nullableType = typeof(Nullable <>).MakeGenericType(_type.GetGenericArguments()[0]); var localValue = ilGenerator.DeclareLocal(nullableType); var localHasValue = ilGenerator.DeclareLocal(typeof(bool)); var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushValue) .Stloc(localValue) .Do(pushWriterOrCtx) .Ldloca(localValue) //Ldloca for struct! .Call(nullableType.GetMethod("get_HasValue")) .Dup() .Stloc(localHasValue) .Callvirt(() => default(AbstractBufferedWriter).WriteBool(false)) .Ldloc(localHasValue) .Brfalse(finish); _itemHandler.Save(ilGenerator, pushWriterOrCtx, il => il .Ldloca(localValue).Call(_type.GetMethod("get_Value")) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[0], _itemHandler.HandledType()))); ilGenerator.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 Save(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen>?pushCtx, Action <IILGen> pushValue) { var nullableType = typeof(Nullable <>).MakeGenericType(_type !.GetGenericArguments()[0]); var localValue = ilGenerator.DeclareLocal(nullableType); var localHasValue = ilGenerator.DeclareLocal(typeof(bool)); var finish = ilGenerator.DefineLabel(); ilGenerator .Do(pushValue) .Stloc(localValue) .Do(pushWriter) .Ldloca(localValue) //ref for struct! .Call(nullableType.GetMethod("get_HasValue") !) .Dup() .Stloc(localHasValue) .Call(typeof(SpanWriter).GetMethod(nameof(SpanWriter.WriteBool)) !) .Ldloc(localHasValue) .Brfalse(finish); _itemHandler.Save(ilGenerator, pushWriter, pushCtx, il => il .Ldloca(localValue).Call(_type.GetMethod("get_Value") !) .Do(_typeConvertorGenerator.GenerateConversion(_type.GetGenericArguments()[0], _itemHandler.HandledType()) !)); ilGenerator.Mark(finish); }
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 localEnumerator = ilGenerator.DeclareLocal(typeAsIEnumerator); 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); _itemsHandler.Save(ilGenerator, pushWriter, pushCtx, il => il .Ldloc(localEnumerator) .Callvirt(typeAsIEnumerator.GetProperty("Current") !.GetGetMethod() !) .Do(_typeConvertGenerator.GenerateConversion(_type.GetGenericArguments()[0], _itemsHandler.HandledType()) !)); ilGenerator .Br(next) .Mark(finish) .Finally() .Ldloc(localEnumerator) .Callvirt(() => default(IDisposable).Dispose()) .EndTry() .Mark(realFinish); }
public void GenerateTypeIterator(IILGen ilGenerator, Action <IILGen> pushObj, Action <IILGen> pushCtx, Type type) { var finish = ilGenerator.DefineLabel(); var itemType = _nullableTypeDescriptor.GetPreferredType(type).GetGenericArguments()[0]; var nullableType = typeof(Nullable <>).MakeGenericType(itemType); var localValue = ilGenerator.DeclareLocal(nullableType); ilGenerator .Do(pushObj) .Stloc(localValue) .Ldloca(localValue) .Call(nullableType.GetMethod("get_HasValue")) .Brfalse(finish) .Ldloca(localValue) .Call(nullableType.GetMethod("get_Value")) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)) .Mark(finish); }
public void GenerateSave(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen> pushCtx, Action <IILGen> pushValue, Type valueType) { if (GetPreferedType() != valueType) { throw new ArgumentException("value type does not match my type"); } var locValue = ilGenerator.DeclareLocal(_type, "value"); ilGenerator .Do(pushValue) .Stloc(locValue); foreach (var pairi in _fields) { var pair = pairi; var methodInfo = _type.GetProperties().First(p => GetPersitentName(p) == pair.Key).GetGetMethod(); pair.Value.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloc(locValue).Callvirt(methodInfo), methodInfo.ReturnType); } }
public bool FreeContent(IILGen ilGenerator, Action <IILGen> pushReaderOrCtx) { var fakeMethod = ILBuilder.Instance.NewMethod <Action>("Relation_fake"); var fakeGenerator = fakeMethod.Generator; if (_keysHandler.FreeContent(fakeGenerator, _ => { })) { throw new BTDBException("Not supported IDictionary in IDictionary key"); } var containsNestedIDictionaries = _valuesHandler.FreeContent(fakeGenerator, _ => { }); if (!containsNestedIDictionaries) { ilGenerator .Do(pushReaderOrCtx) .Castclass(typeof(IDBReaderCtx)) .Do(Extensions.PushReaderFromCtx(pushReaderOrCtx)) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt64()) .Callvirt(() => default(IDBReaderCtx).RegisterDict(0ul)); } else { var genericArguments = _type.GetGenericArguments(); var instanceType = typeof(ODBDictionary <,>).MakeGenericType(genericArguments); var dictId = ilGenerator.DeclareLocal(typeof(ulong)); ilGenerator .Do(pushReaderOrCtx) .Castclass(typeof(IDBReaderCtx)) .Do(Extensions.PushReaderFromCtx(pushReaderOrCtx)) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt64()) .Stloc(dictId) .Ldloc(dictId) .Callvirt(() => default(IDBReaderCtx).RegisterDict(0ul)) .Do(pushReaderOrCtx) .Ldloc(dictId) .LdcI4(_configurationId) //ODBDictionary.DoFreeContent(IReaderCtx ctx, ulong id, int cfgId) .Call(instanceType.GetMethod("DoFreeContent")); } return(true); }
public NeedsFreeContent FreeContent(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx) { var fakeMethod = ILBuilder.Instance.NewMethod <Action>("Relation_fake"); var fakeGenerator = fakeMethod.Generator; if (_keysHandler.FreeContent(fakeGenerator, _ => { }, _ => { }) == NeedsFreeContent.Yes) { throw new BTDBException("Not supported 'free content' in IDictionary key"); } if (_valuesHandler.FreeContent(fakeGenerator, _ => { }, _ => { }) == NeedsFreeContent.No) { ilGenerator .Do(pushCtx) .Castclass(typeof(IDBReaderCtx)) .Do(pushReader) .Call(typeof(SpanReader).GetMethod(nameof(SpanReader.ReadVUInt64)) !) .Callvirt(() => default(IDBReaderCtx).RegisterDict(0ul)); } else { var genericArguments = _type !.GetGenericArguments(); var instanceType = typeof(ODBDictionary <,>).MakeGenericType(genericArguments); var dictId = ilGenerator.DeclareLocal(typeof(ulong)); ilGenerator .Do(pushCtx) .Castclass(typeof(IDBReaderCtx)) .Do(pushReader) .Call(typeof(SpanReader).GetMethod(nameof(SpanReader.ReadVUInt64)) !) .Stloc(dictId) .Ldloc(dictId) .Callvirt(() => default(IDBReaderCtx).RegisterDict(0ul)) .Do(pushCtx) .Ldloc(dictId) .LdcI4(GetConfigurationId(_type)) //ODBDictionary.DoFreeContent(IReaderCtx ctx, ulong id, int cfgId) .Call(instanceType.GetMethod(nameof(ODBDictionary <int, int> .DoFreeContent)) !); } return(NeedsFreeContent.Yes); }
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); }
void SaveKeyBytesAndCallMethod(IILGen ilGenerator, Type relationDBManipulatorType, string methodName, ParameterInfo[] methodParameters, Type methodReturnType, IDictionary <string, MethodInfo> apartFields) { var writerLoc = ilGenerator.DeclareLocal(typeof(ByteBufferWriter)); ilGenerator.Newobj(() => new ByteBufferWriter()); ilGenerator.Stloc(writerLoc); Action <IILGen> pushWriter = il => il.Ldloc(writerLoc); //arg0 = this = manipulator if (methodName.StartsWith("RemoveById")) { CreateMethodRemoveById(ilGenerator, relationDBManipulatorType, methodName, methodParameters, methodReturnType, apartFields, pushWriter, writerLoc); } else if (methodName.StartsWith("FindById")) { CreateMethodFindById(ilGenerator, relationDBManipulatorType, methodName, methodParameters, methodReturnType, apartFields, pushWriter, writerLoc); } else if (methodName.StartsWith("FindBy")) { CreateMethodFindBy(ilGenerator, relationDBManipulatorType, methodName, methodParameters, methodReturnType, apartFields, pushWriter, writerLoc); } else if (methodName == "ListById") { CreateMethodListById(ilGenerator, relationDBManipulatorType, methodName, methodParameters, apartFields, pushWriter, writerLoc); } else if (methodName == "Contains") { CreateMethodContains(ilGenerator, relationDBManipulatorType, methodParameters, apartFields, pushWriter, writerLoc); } else { throw new NotSupportedException(); } }
public void Load(IILGen ilGenerator, Action <IILGen> pushReaderOrCtx) { var localResult = ilGenerator.DeclareLocal(HandledType()); var finish = ilGenerator.DefineLabel(); var noValue = ilGenerator.DefineLabel(); var itemType = _type.GetGenericArguments()[0]; var nullableType = typeof(Nullable <>).MakeGenericType(itemType); ilGenerator .Do(pushReaderOrCtx) .Callvirt(() => default(AbstractBufferedReader).ReadBool()) .Brfalse(noValue); _itemHandler.Load(ilGenerator, pushReaderOrCtx); _typeConvertorGenerator.GenerateConversion(_itemHandler.HandledType(), itemType)(ilGenerator); ilGenerator .Newobj(nullableType.GetConstructor(new[] { itemType })) .Stloc(localResult) .BrS(finish) .Mark(noValue) .Ldloca(localResult) .InitObj(nullableType) .Mark(finish) .Ldloc(localResult); }
public void Load(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen>?pushCtx) { var localResult = ilGenerator.DeclareLocal(HandledType()); var finish = ilGenerator.DefineLabel(); var noValue = ilGenerator.DefineLabel(); var itemType = _type !.GetGenericArguments()[0]; var nullableType = typeof(Nullable <>).MakeGenericType(itemType); ilGenerator .Do(pushReader) .Call(typeof(SpanReader).GetMethod(nameof(SpanReader.ReadBool)) !) .Brfalse(noValue); _itemHandler.Load(ilGenerator, pushReader, pushCtx); _typeConvertorGenerator.GenerateConversion(_itemHandler.HandledType(), itemType) !(ilGenerator); ilGenerator .Newobj(nullableType.GetConstructor(new[] { itemType }) !) .Stloc(localResult) .BrS(finish) .Mark(noValue) .Ldloca(localResult) .InitObj(nullableType) .Mark(finish) .Ldloc(localResult); }
public void GenerateLoad(IILGen ilGenerator, Action<IILGen> pushReader, Action<IILGen> pushCtx, Action<IILGen> pushDescriptor, Type targetType) { var localCount = ilGenerator.DeclareLocal(typeof(int)); var itemType = _typeSerializers.LoadAsType(_itemDescriptor); var listType = typeof(ListWithDescriptor<>).MakeGenericType(itemType); if (!targetType.IsAssignableFrom(listType)) throw new NotSupportedException(); var localList = ilGenerator.DeclareLocal(listType); var loadFinished = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .ConvI4() .Dup() .Stloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Dup() .Stloc(localCount) .Do(pushDescriptor) .Newobj(listType.GetConstructor(new[] { typeof(int), typeof(ITypeDescriptor) })) .Stloc(localList) .Mark(next) .Ldloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Stloc(localCount) .Ldloc(localList); _itemDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(0).Callvirt(() => default(ITypeDescriptor).NestedType(0)), itemType); ilGenerator .Callvirt(listType.GetInterface("ICollection`1").GetMethod("Add")) .Br(next) .Mark(loadFinished) .Ldloc(localList) .Castclass(targetType); }
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 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 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 GenerateSave(IILGen ilGenerator, Action<IILGen> pushWriter, Action<IILGen> pushCtx, Action<IILGen> pushValue, Type valueType) { if (GetPreferedType() != valueType) throw new ArgumentException("value type does not match my type"); var locValue = ilGenerator.DeclareLocal(_type, "value"); ilGenerator .Do(pushValue) .Stloc(locValue); foreach (var pairi in _fields) { var pair = pairi; var methodInfo = _type.GetProperties().First(p => GetPersitentName(p) == pair.Key).GetGetMethod(); pair.Value.GenerateSaveEx(ilGenerator, pushWriter, pushCtx, il => il.Ldloc(locValue).Callvirt(methodInfo), methodInfo.ReturnType); } }
public void ReplayTo(IILGen target) { Local = target.DeclareLocal(_type, _name, _pinned); Debug.Assert(Local.Index == Index); }
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 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 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 GenerateTypeIterator(IILGen ilGenerator, Action<IILGen> pushObj, Action<IILGen> pushCtx) { var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); var itemType = _listTypeDescriptor._typeSerializers.LoadAsType(_listTypeDescriptor._itemDescriptor); var localList = ilGenerator.DeclareLocal(typeof(IList<>).MakeGenericType(itemType)); var localIndex = ilGenerator.DeclareLocal(typeof(int)); var localCount = ilGenerator.DeclareLocal(typeof(int)); ilGenerator .Do(pushObj) .Castclass(localList.LocalType) .Dup() .Stloc(localList) .Callvirt(localList.LocalType.GetInterface("ICollection`1").GetProperty("Count").GetGetMethod()) .Stloc(localCount) .LdcI4(0) .Stloc(localIndex) .Mark(next) .Ldloc(localIndex) .Ldloc(localCount) .BgeUn(finish) .Do(pushCtx) .Ldloc(localList) .Ldloc(localIndex) .Callvirt(localList.LocalType.GetMethod("get_Item")) .Callvirt(() => default(IDescriptorSerializerLiteContext).StoreNewDescriptors(null)) .Ldloc(localIndex) .LdcI4(1) .Add() .Stloc(localIndex) .Br(next) .Mark(finish); }
public bool FreeContent(IILGen ilGenerator, Action<IILGen> pushReaderOrCtx) { var fakeMethod = ILBuilder.Instance.NewMethod<Action>("Relation_fake"); var fakeGenerator = fakeMethod.Generator; if (_keysHandler.FreeContent(fakeGenerator, _ => { })) throw new BTDBException("Not supported IDictionary in IDictionary key"); var containsNestedIDictionaries = _valuesHandler.FreeContent(fakeGenerator, _ => { }); if (!containsNestedIDictionaries) { ilGenerator .Do(pushReaderOrCtx) .Castclass(typeof(IDBReaderCtx)) .Do(Extensions.PushReaderFromCtx(pushReaderOrCtx)) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt64()) .Callvirt(() => default(IDBReaderCtx).RegisterDict(0ul)); } else { var genericArguments = _type.GetGenericArguments(); var instanceType = typeof(ODBDictionary<,>).MakeGenericType(genericArguments); var dictId = ilGenerator.DeclareLocal(typeof(ulong)); ilGenerator .Do(pushReaderOrCtx) .Castclass(typeof(IDBReaderCtx)) .Do(Extensions.PushReaderFromCtx(pushReaderOrCtx)) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt64()) .Stloc(dictId) .Ldloc(dictId) .Callvirt(() => default(IDBReaderCtx).RegisterDict(0ul)) .Do(pushReaderOrCtx) .Ldloc(dictId) .LdcI4(_configurationId) //ODBDictionary.DoFreeContent(IReaderCtx ctx, ulong id, int cfgId) .Call(instanceType.GetMethod("DoFreeContent")); } return true; }
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 GenerateLoad(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx, Action <IILGen> pushDescriptor, Type targetType) { if (targetType == typeof(object)) { targetType = GetPreferedType(); } var localCount = ilGenerator.DeclareLocal(typeof(int)); var targetIList = targetType.GetInterface("IList`1") ?? targetType; var targetTypeArguments = targetIList.GetGenericArguments(); var itemType = _typeSerializers.LoadAsType(_itemDescriptor, targetTypeArguments[0]); if (targetType.IsArray) { var localArray = ilGenerator.DeclareLocal(targetType); var loadFinished = ilGenerator.DefineLabel(); var localIndex = ilGenerator.DeclareLocal(typeof(int)); var next = ilGenerator.DefineLabel(); ilGenerator .LdcI4(0) .Stloc(localIndex) .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .ConvI4() .Dup() .Stloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Dup() .Stloc(localCount) .Newarr(itemType) .Stloc(localArray) .Mark(next) .Ldloc(localCount) .Ldloc(localIndex) .Sub() .Brfalse(loadFinished) .Ldloc(localArray) .Ldloc(localIndex); _itemDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(0).Callvirt(() => default(ITypeDescriptor).NestedType(0)), itemType, _convertorGenerator); ilGenerator .Stelem(itemType) .Ldloc(localIndex) .LdcI4(1) .Add() .Stloc(localIndex) .Br(next) .Mark(loadFinished) .Ldloc(localArray) .Castclass(targetType); } else { var listType = typeof(ListWithDescriptor <>).MakeGenericType(itemType); if (!targetType.IsAssignableFrom(listType)) { throw new NotSupportedException($"List type {listType.ToSimpleName()} is not assignable to {targetType.ToSimpleName()}."); } var localList = ilGenerator.DeclareLocal(listType); var loadFinished = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .ConvI4() .Dup() .Stloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Dup() .Stloc(localCount) .Do(pushDescriptor) .Newobj(listType.GetConstructor(new[] { typeof(int), typeof(ITypeDescriptor) })) .Stloc(localList) .Mark(next) .Ldloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Stloc(localCount) .Ldloc(localList); _itemDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(0).Callvirt(() => default(ITypeDescriptor).NestedType(0)), itemType, _convertorGenerator); ilGenerator .Callvirt(listType.GetInterface("ICollection`1").GetMethod("Add")) .Br(next) .Mark(loadFinished) .Ldloc(localList) .Castclass(targetType); } }
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 static void GenerateJumpIfEqual(IILGen ilGenerator, Type type, IILLabel jumpTo, Action <IILGen> loadLeft, Action <IILGen> loadRight) { if (type == typeof(sbyte) || type == typeof(byte) || type == typeof(short) || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong) || type == typeof(float) || type == typeof(double) || type == typeof(bool) || type.IsEnum) { ilGenerator .Do(loadLeft) .Do(loadRight) .BeqS(jumpTo); return; } if (type.IsGenericType) { var genType = type.GetGenericTypeDefinition(); if (genType == typeof(Nullable <>)) { var localLeft = ilGenerator.DeclareLocal(type, "left"); var localRight = ilGenerator.DeclareLocal(type, "right"); var hasValueMethod = type.GetMethod("get_HasValue"); var getValueMethod = type.GetMethod("GetValueOrDefault", Type.EmptyTypes); var labelLeftHasValue = ilGenerator.DefineLabel("leftHasValue"); var labelDifferent = ilGenerator.DefineLabel("different"); ilGenerator .Do(loadLeft) .Stloc(localLeft) .Do(loadRight) .Stloc(localRight) .Ldloca(localLeft) .Call(hasValueMethod) .BrtrueS(labelLeftHasValue) .Ldloca(localRight) .Call(hasValueMethod) .BrtrueS(labelDifferent) .BrS(jumpTo) .Mark(labelLeftHasValue) .Ldloca(localRight) .Call(hasValueMethod) .BrfalseS(labelDifferent); GenerateJumpIfEqual( ilGenerator, type.GetGenericArguments()[0], jumpTo, g => g.Ldloca(localLeft).Call(getValueMethod), g => g.Ldloca(localRight).Call(getValueMethod)); ilGenerator.Mark(labelDifferent); return; } } var equalsMethod = type.GetMethod("Equals", new[] { type, type }) ?? type.GetMethod("op_Equality", new[] { type, type }); if (equalsMethod != null) { loadLeft(ilGenerator); loadRight(ilGenerator); ilGenerator .Call(equalsMethod) .BrtrueS(jumpTo); return; } throw new ArgumentOutOfRangeException(nameof(type), $"Don't know how to compare type {type}"); }
public void GenerateLoad(IILGen ilGenerator, Action<IILGen> pushReader, Action<IILGen> pushCtx, Action<IILGen> pushDescriptor, Type targetType) { var localCount = ilGenerator.DeclareLocal(typeof(int)); var targetIDictionary = targetType.GetInterface("IDictionary`2") ?? targetType; var targetTypeArguments = targetIDictionary.GetGenericArguments(); var keyType = _typeSerializers.LoadAsType(_keyDescriptor, targetTypeArguments[0]); var valueType = _typeSerializers.LoadAsType(_valueDescriptor, targetTypeArguments[1]); var dictionaryType = typeof(DictionaryWithDescriptor<,>).MakeGenericType(keyType, valueType); if (!targetType.IsAssignableFrom(dictionaryType)) throw new InvalidOperationException(); var localDict = ilGenerator.DeclareLocal(dictionaryType); var loadFinished = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReader) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .ConvI4() .Dup() .LdcI4(1) .Sub() .Stloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .Do(pushDescriptor) .Newobj(dictionaryType.GetConstructor(new[] { typeof(int), typeof(ITypeDescriptor) })) .Stloc(localDict) .Mark(next) .Ldloc(localCount) .Brfalse(loadFinished) .Ldloc(localCount) .LdcI4(1) .Sub() .Stloc(localCount) .Ldloc(localDict); _keyDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(0).Callvirt(() => default(ITypeDescriptor).NestedType(0)), keyType, _convertorGenerator); _valueDescriptor.GenerateLoadEx(ilGenerator, pushReader, pushCtx, il => il.Do(pushDescriptor).LdcI4(1).Callvirt(() => default(ITypeDescriptor).NestedType(0)), valueType, _convertorGenerator); ilGenerator .Callvirt(dictionaryType.GetMethod("Add")) .Br(next) .Mark(loadFinished) .Ldloc(localDict) .Castclass(targetType); }
public void Skip(IILGen ilGenerator, Action<IILGen> pushReaderOrCtx) { var localCount = ilGenerator.DeclareLocal(typeof(uint)); var finish = ilGenerator.DefineLabel(); var next = ilGenerator.DefineLabel(); ilGenerator .Do(pushReaderOrCtx) .Callvirt(() => default(IReaderCtx).SkipObject()) .Brfalse(finish) .Do(Extensions.PushReaderFromCtx(pushReaderOrCtx)) .Callvirt(() => default(AbstractBufferedReader).ReadVUInt32()) .Stloc(localCount) .Mark(next) .Ldloc(localCount) .Brfalse(finish) .Ldloc(localCount) .LdcI4(1) .Sub() .ConvU4() .Stloc(localCount) .GenerateSkip(_itemsHandler, pushReaderOrCtx) .Br(next) .Mark(finish); }
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> 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); }
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); } }