Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
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);
            }
        }