예제 #1
0
        protected override void EmitWrite(CompilerContext ctx, Local valueFrom)
        {
            Type       itemType = typeof(KeyValuePair <TKey, TValue>);
            MethodInfo moveNext, current, getEnumerator = ListDecorator.GetEnumeratorInfo(ctx.Model,
                                                                                          ExpectedType, itemType, out moveNext, out current);
            Type enumeratorType = getEnumerator.ReturnType;

            MethodInfo key    = itemType.GetProperty(nameof(KeyValuePair <TKey, TValue> .Key)).GetGetMethod(),
                       @value = itemType.GetProperty(nameof(KeyValuePair <TKey, TValue> .Value)).GetGetMethod();

            using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom))
                using (Compiler.Local iter = new Compiler.Local(ctx, enumeratorType))
                    using (Compiler.Local token = new Compiler.Local(ctx, typeof(SubItemToken)))
                        using (Compiler.Local kvp = new Compiler.Local(ctx, itemType))
                        {
                            ctx.LoadAddress(list, ExpectedType);
                            ctx.EmitCall(getEnumerator, ExpectedType);
                            ctx.StoreValue(iter);
                            using (ctx.Using(iter))
                            {
                                Compiler.CodeLabel body = ctx.DefineLabel(), next = ctx.DefineLabel();
                                ctx.Branch(next, false);

                                ctx.MarkLabel(body);

                                ctx.LoadAddress(iter, enumeratorType);
                                ctx.EmitCall(current, enumeratorType);

                                if (itemType != ctx.MapType(typeof(object)) && current.ReturnType == ctx.MapType(typeof(object)))
                                {
                                    ctx.CastFromObject(itemType);
                                }
                                ctx.StoreValue(kvp);

                                ctx.LoadValue(fieldNumber);
                                ctx.LoadValue((int)wireType);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("WriteFieldHeader"));

                                ctx.LoadNullRef();
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("StartSubItem"));
                                ctx.StoreValue(token);

                                ctx.LoadAddress(kvp, itemType);
                                ctx.EmitCall(key, itemType);
                                ctx.WriteNullCheckedTail(typeof(TKey), keyTail, null);

                                ctx.LoadAddress(kvp, itemType);
                                ctx.EmitCall(value, itemType);
                                ctx.WriteNullCheckedTail(typeof(TValue), Tail, null);

                                ctx.LoadValue(token);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("EndSubItem"));

                                ctx.MarkLabel(@next);
                                ctx.LoadAddress(iter, enumeratorType);
                                ctx.EmitCall(moveNext, enumeratorType);
                                ctx.BranchIfTrue(body, false);
                            }
                        }
        }