public static IILGen Callvirt <T>(this IILGen il, Expression <Func <T> > expression) { var newExpression = expression.Body as MemberExpression; if (newExpression != null) { return(il.Callvirt(((PropertyInfo)newExpression.Member).GetGetMethod(true))); } var methodInfo = (expression.Body as MethodCallExpression).Method; return(il.Callvirt(methodInfo)); }
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(); } } }
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")); }
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 static IILGen Callvirt <T>(this IILGen il, Expression <Func <T> > expression) { if (expression.Body is MemberExpression newExpression) { return(il.Callvirt(((PropertyInfo)newExpression.Member).GetGetMethod(true) !)); } var methodInfo = ((MethodCallExpression)expression.Body).Method; return(il.Callvirt(methodInfo)); }
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 targetIDictionary = GetInterface(targetType); var targetTypeArguments = targetIDictionary.GetGenericArguments(); var keyType = _typeSerializers.LoadAsType(_keyDescriptor, targetTypeArguments[0]); var valueType = _typeSerializers.LoadAsType(_valueDescriptor, targetTypeArguments[1]); var dictionaryTypeGenericDefinition = targetType.InheritsOrImplements(typeof(IOrderedDictionary <,>)) ? typeof(OrderedDictionaryWithDescriptor <,>) : typeof(DictionaryWithDescriptor <,>); var dictionaryType = dictionaryTypeGenericDefinition.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(nameof(IDictionary.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) { pushCtx(ilGenerator); ilGenerator.Callvirt(() => ((ITypeBinaryDeserializerContext)null).LoadEncryptedString()); if (targetType != typeof(object)) { if (targetType != GetPreferedType()) { throw new ArgumentOutOfRangeException(nameof(targetType)); } return; } ilGenerator.Box(GetPreferedType()); }
public void GenerateLoad(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx, Action <IILGen> pushDescriptor, Type targetType) { var localCount = ilGenerator.DeclareLocal(typeof(int)); var targetIList = targetType.GetInterface("IList`1") ?? targetType; var targetTypeArguments = targetIList.GetGenericArguments(); var itemType = _typeSerializers.LoadAsType(_itemDescriptor, targetTypeArguments[0]); 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 GenerateLoad(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx, Action <IILGen> pushDescriptor, Type targetType) { var localCount = ilGenerator.DeclareLocal(typeof(int)); var keyType = _typeSerializers.LoadAsType(_keyDescriptor); var valueType = _typeSerializers.LoadAsType(_valueDescriptor); 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); }
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)); }
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) { 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 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 GenerateSkip(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx) { pushCtx(ilGenerator); ilGenerator.Callvirt(() => ((ITypeBinaryDeserializerContext)null).SkipEncryptedString()); }
public void Skip(IILGen ilGenerator, Action <IILGen> pushReaderOrCtx) { pushReaderOrCtx(ilGenerator); ilGenerator.Callvirt(() => ((IReaderCtx)null).SkipEncryptedString()); }
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 IILGen Callvirt(this IILGen il, Expression <Action> expression) { var methodInfo = (expression.Body as MethodCallExpression).Method; return(il.Callvirt(methodInfo)); }