public static bool IsStampNeeded(TypeDescriptor type, bool treatCollectionAsUserObject) { return(!Helpers.IsWriteableByPrimitiveWriter(type.UnderlyingType) && (!CollectionMetaToken.IsCollection(type) || treatCollectionAsUserObject)); }
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); }
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); }