示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        public void Save(IILGen ilGenerator, Action <IILGen> pushWriter, Action <IILGen> pushCtx,
                         Action <IILGen> pushValue)
        {
            var realFinish          = ilGenerator.DefineLabel();
            var finish              = ilGenerator.DefineLabel();
            var next                = ilGenerator.DefineLabel();
            var localValue          = ilGenerator.DeclareLocal(_type !);
            var typeAsICollection   = _type.GetInterface("ICollection`1");
            var typeAsIEnumerable   = _type.GetInterface("IEnumerable`1");
            var getEnumeratorMethod = typeAsIEnumerable !.GetMethod("GetEnumerator");
            var typeAsIEnumerator   = getEnumeratorMethod !.ReturnType;
            var typeKeyValuePair    = typeAsICollection !.GetGenericArguments()[0];
            var localEnumerator     = ilGenerator.DeclareLocal(typeAsIEnumerator);
            var localPair           = ilGenerator.DeclareLocal(typeKeyValuePair);

            ilGenerator
            .Do(pushValue)
            .Stloc(localValue)
            .Do(pushCtx)
            .Do(pushWriter)
            .Ldloc(localValue)
            .Castclass(typeof(object))
            .Callvirt(typeof(IWriterCtx).GetMethod(nameof(IWriterCtx.WriteObject)) !)
            .Brfalse(realFinish)
            .Do(pushWriter)
            .Ldloc(localValue)
            .Callvirt(typeAsICollection.GetProperty("Count") !.GetGetMethod() !)
            .ConvU4()
            .Call(typeof(SpanWriter).GetMethod(nameof(SpanWriter.WriteVUInt32)) !)
            .Ldloc(localValue)
            .Callvirt(getEnumeratorMethod)
            .Stloc(localEnumerator)
            .Try()
            .Mark(next)
            .Ldloc(localEnumerator)
            .Callvirt(() => default(IEnumerator).MoveNext())
            .Brfalse(finish)
            .Ldloc(localEnumerator)
            .Callvirt(typeAsIEnumerator.GetProperty("Current") !.GetGetMethod() !)
            .Stloc(localPair);
            var keyAndValueTypes = _type.GetGenericArguments();

            _keysHandler.Save(ilGenerator, pushWriter, pushCtx, il => il
                              .Ldloca(localPair)
                              .Call(typeKeyValuePair.GetProperty("Key") !.GetGetMethod() !)
                              .Do(_typeConvertGenerator.GenerateConversion(keyAndValueTypes[0], _keysHandler.HandledType()) !));
            _valuesHandler.Save(ilGenerator, pushWriter, pushCtx, il => il
                                .Ldloca(localPair)
                                .Call(typeKeyValuePair.GetProperty("Value") !.GetGetMethod() !)
                                .Do(_typeConvertGenerator.GenerateConversion(keyAndValueTypes[1], _valuesHandler.HandledType()) !));
            ilGenerator
            .Br(next)
            .Mark(finish)
            .Finally()
            .Ldloc(localEnumerator)
            .Callvirt(() => default(IDisposable).Dispose())
            .EndTry()
            .Mark(realFinish);
        }
示例#4
0
        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);
        }
示例#5
0
        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);
            }
        }
示例#6
0
 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();
 }
示例#7
0
 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);
 }
示例#8
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);
     }
 }
示例#9
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);
            }
        }
示例#10
0
            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();
            }
示例#11
0
 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();
 }
示例#12
0
 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);
 }