public ArrayDecorator(TypeModel model, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, Type arrayType, bool overwriteList, bool supportNull) : base(tail) { this.itemType = arrayType.GetElementType(); if (!supportNull) { Helpers.GetUnderlyingType(this.itemType); } if ((writePacked || (packedWireType != WireType.None)) && (fieldNumber <= 0)) { throw new ArgumentOutOfRangeException("fieldNumber"); } if (!ListDecorator.CanPack(packedWireType)) { if (writePacked) { throw new InvalidOperationException("Only simple data-types can use packed encoding"); } packedWireType = WireType.None; } this.fieldNumber = fieldNumber; this.packedWireType = packedWireType; if (writePacked) { this.options = (byte)(this.options | 1); } if (overwriteList) { this.options = (byte)(this.options | 2); } if (supportNull) { this.options = (byte)(this.options | 4); } this.arrayType = arrayType; }
public TupleSerializer(RuntimeTypeModel model, ConstructorInfo ctor, MemberInfo[] members) { if (ctor == null) { throw new ArgumentNullException("ctor"); } if (members == null) { throw new ArgumentNullException("members"); } this.ctor = ctor; this.members = members; this.tails = new IProtoSerializer[members.Length]; ParameterInfo[] parameters = ctor.GetParameters(); for (int i = 0; i < members.Length; i++) { WireType type; IProtoSerializer serializer2; Type parameterType = parameters[i].ParameterType; Type itemType = null; Type defaultType = null; MetaType.ResolveListTypes(model, parameterType, ref itemType, ref defaultType); Type type5 = (itemType == null) ? parameterType : itemType; bool asReference = false; if (model.FindOrAddAuto(type5, false, true, false) >= 0) { asReference = model[type5].AsReferenceDefault; } IProtoSerializer tail = ValueMember.TryGetCoreSerializer(model, DataFormat.Default, type5, out type, asReference, false, false, true); if (tail == null) { throw new InvalidOperationException("No serializer defined for type: " + type5.FullName); } tail = new TagDecorator(i + 1, type, false, tail); if (itemType == null) { serializer2 = tail; } else if (parameterType.IsArray) { serializer2 = new ArrayDecorator(model, tail, i + 1, false, type, parameterType, false, false); } else { serializer2 = new ListDecorator(model, parameterType, defaultType, tail, i + 1, false, type, true, false, false); } this.tails[i] = serializer2; } }
protected override void EmitRead(CompilerContext ctx, Local valueFrom) { Type type = ctx.MapType(typeof(List <>)).MakeGenericType(new Type[] { this.itemType }); Type expectedType = this.ExpectedType; using (Local local = this.AppendToCollection ? ctx.GetLocalWithValue(expectedType, valueFrom) : null) { using (Local local2 = new Local(ctx, expectedType)) { using (Local local3 = new Local(ctx, type)) { ctx.EmitCtor(type); ctx.StoreValue(local3); ListDecorator.EmitReadList(ctx, local3, base.Tail, type.GetMethod("Add"), this.packedWireType, false); using (Local local4 = this.AppendToCollection ? new Local(ctx, ctx.MapType(typeof(int))) : null) { Type[] types = new Type[] { ctx.MapType(typeof(Array)), ctx.MapType(typeof(int)) }; if (this.AppendToCollection) { ctx.LoadLength(local, true); ctx.CopyValue(); ctx.StoreValue(local4); ctx.LoadAddress(local3, type); ctx.LoadValue(type.GetProperty("Count")); ctx.Add(); ctx.CreateArray(this.itemType, null); ctx.StoreValue(local2); ctx.LoadValue(local4); CodeLabel label = ctx.DefineLabel(); ctx.BranchIfFalse(label, true); ctx.LoadValue(local); ctx.LoadValue(local2); ctx.LoadValue(0); ctx.EmitCall(expectedType.GetMethod("CopyTo", types)); ctx.MarkLabel(label); ctx.LoadValue(local3); ctx.LoadValue(local2); ctx.LoadValue(local4); } else { ctx.LoadAddress(local3, type); ctx.LoadValue(type.GetProperty("Count")); ctx.CreateArray(this.itemType, null); ctx.StoreValue(local2); ctx.LoadAddress(local3, type); ctx.LoadValue(local2); ctx.LoadValue(0); } types[0] = expectedType; MethodInfo method = type.GetMethod("CopyTo", types); if (method == null) { types[1] = ctx.MapType(typeof(Array)); method = type.GetMethod("CopyTo", types); } ctx.EmitCall(method); } ctx.LoadValue(local2); } } } }