コード例 #1
0
 public static bool IsStampNeeded(TypeDescriptor type, bool treatCollectionAsUserObject)
 {
     return(!Helpers.IsWriteableByPrimitiveWriter(type.UnderlyingType) && (!CollectionMetaToken.IsCollection(type) || treatCollectionAsUserObject));
 }
コード例 #2
0
        private void GenerateWriteCollection(CollectionMetaToken token)
        {
            Type enumerableType;
            Type enumeratorType;
            if(token.IsDictionary)
            {
                enumerableType = typeof(IDictionary);
                enumeratorType = typeof(IDictionaryEnumerator);
            }
            else
            {
                var genericTypes = new [] { token.FormalElementType };

                enumerableType = token.IsGenericallyIterable ? typeof(IEnumerable<>).MakeGenericType(genericTypes) : typeof(IEnumerable);
                enumeratorType = token.IsGenericallyIterable ? typeof(IEnumerator<>).MakeGenericType(genericTypes) : typeof(IEnumerator);
            }

            generator.DeclareLocal(enumeratorType); // iterator
            if(token.IsDictionary)
            {
                generator.DeclareLocal(token.FormalKeyType);
                generator.DeclareLocal(token.FormalValueType);
            }
            else
            {
                generator.DeclareLocal(token.FormalElementType);
            }

            // length of the collection
            generator.Emit(OpCodes.Ldarg_1); // primitiveWriter
            generator.Emit(OpCodes.Ldarg_2); // collection to serialize
            if(token.CountMethod.IsStatic)
            {
                generator.Emit(OpCodes.Call, token.CountMethod);
            }
            else
            {
                generator.Emit(OpCodes.Callvirt, token.CountMethod);
            }
            generator.Emit(OpCodes.Call, primitiveWriterWriteInteger);

            // elements
            var getEnumeratorMethod = enumerableType.GetMethod("GetEnumerator");
            generator.Emit(OpCodes.Ldarg_2); // collection to serialize
            generator.Emit(OpCodes.Call, getEnumeratorMethod);
            generator.Emit(OpCodes.Stloc_0);
            var loopBegin = generator.DefineLabel();
            generator.MarkLabel(loopBegin);
            generator.Emit(OpCodes.Ldloc_0);
            var finish = generator.DefineLabel();
            generator.Emit(OpCodes.Call, Helpers.GetMethodInfo<IEnumerator>(x => x.MoveNext()));
            generator.Emit(OpCodes.Brfalse, finish);
            generator.Emit(OpCodes.Ldloc_0);
            if(token.IsDictionary)
            {
                // key
                generator.Emit(OpCodes.Nop);
                generator.Emit(OpCodes.Call, enumeratorType.GetProperty("Key").GetGetMethod());
                generator.Emit(OpCodes.Unbox_Any, token.FormalKeyType);
                generator.Emit(OpCodes.Stloc_1);
                GenerateWriteType(gen => gen.Emit(OpCodes.Ldloc_1), token.FormalKeyType);

                // value
                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Call, enumeratorType.GetProperty("Value").GetGetMethod());
                generator.Emit(OpCodes.Unbox_Any, token.FormalValueType);
                generator.Emit(OpCodes.Stloc_2);
                GenerateWriteType(gen => gen.Emit(OpCodes.Ldloc_2), token.FormalValueType);
            }
            else
            {
                generator.Emit(OpCodes.Call, enumeratorType.GetProperty("Current").GetGetMethod());
                generator.Emit(OpCodes.Stloc_1);
	
                // operation on current element
                GenerateWriteTypeLocal1(token.FormalElementType);
            }

            generator.Emit(OpCodes.Br, loopBegin);
            generator.MarkLabel(finish);
        }
コード例 #3
0
        private static void GenerateWriteEnumerable(WriterGenerationContext context, Variable valueLocal, CollectionMetaToken token)
        {
            var genericTypes   = new[] { token.FormalElementType };
            var enumerableType = token.IsGeneric ? typeof(IEnumerable <>).MakeGenericType(genericTypes) : typeof(IEnumerable);
            var enumeratorType = token.IsGeneric ? typeof(IEnumerator <>).MakeGenericType(genericTypes) : typeof(IEnumerator);

            var iteratorLocal       = context.Generator.DeclareLocal(enumeratorType);
            var currentElementLocal = context.Generator.DeclareLocal(token.FormalElementType);
            var elementVariable     = new Variable(currentElementLocal);

            var loopBegin = context.Generator.DefineLabel();
            var finish    = context.Generator.DefineLabel();

            context.PushPrimitiveWriterOntoStack();
            context.Generator.PushVariableOntoStack(valueLocal);
            context.Generator.Emit(token.CountMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt, token.CountMethod);
            context.Generator.Call <PrimitiveWriter>(x => x.Write(0));

            var getEnumeratorMethod = enumerableType.GetMethod("GetEnumerator");

            context.Generator.PushVariableOntoStack(valueLocal);
            context.Generator.Emit(OpCodes.Call, getEnumeratorMethod);
            context.Generator.StoreLocalValueFromStack(iteratorLocal);

            context.Generator.MarkLabel(loopBegin);
            context.Generator.PushLocalValueOntoStack(iteratorLocal);
            context.Generator.Call <IEnumerator>(x => x.MoveNext());
            context.Generator.Emit(OpCodes.Brfalse, finish);

            context.Generator.PushLocalValueOntoStack(iteratorLocal);
            context.Generator.Emit(OpCodes.Call, enumeratorType.GetProperty("Current").GetGetMethod());
            context.Generator.StoreLocalValueFromStack(currentElementLocal);

            GenerateWriteField(context, elementVariable, token.FormalElementType);
            context.Generator.Emit(OpCodes.Br, loopBegin);

            context.Generator.MarkLabel(finish);
        }