コード例 #1
0
ファイル: RelationBuilder.cs プロジェクト: keeema/bbcore
        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);
        }
コード例 #2
0
ファイル: RelationBuilder.cs プロジェクト: wikancz/BTDB
        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"));
        }
コード例 #3
0
ファイル: RelationBuilder.cs プロジェクト: keeema/bbcore
        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);
        }
コード例 #4
0
        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();
                }
            }
        }
コード例 #5
0
ファイル: ListTypeDescriptor.cs プロジェクト: pavolpr/BTDB
        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);
        }
コード例 #6
0
ファイル: RelationBuilder.cs プロジェクト: keeema/bbcore
        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"));
            }
        }
コード例 #7
0
ファイル: ListFieldHandler.cs プロジェクト: wikancz/BTDB
        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);
        }
コード例 #8
0
ファイル: RelationBuilder.cs プロジェクト: wikancz/BTDB
        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));
        }
コード例 #9
0
ファイル: RelationBuilder.cs プロジェクト: keeema/bbcore
        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);
        }
コード例 #10
0
 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);
     }
 }
コード例 #11
0
 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);
     }
 }
コード例 #12
0
ファイル: ListTypeDescriptor.cs プロジェクト: yonglehou/BTDB
 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);
 }
コード例 #13
0
        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);
            }
        }
コード例 #14
0
 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);
     }
 }
コード例 #15
0
ファイル: ListFieldHandler.cs プロジェクト: mano-cz/BTDB
 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);
 }