示例#1
0
        protected override bool InnerGenerate(WriterGenerationContext context)
        {
            var value = new Variable(1);

            WriteMethodGenerator.GenerateWriteDeferredReference(context, value, type);
            return(true);
        }
示例#2
0
        protected override bool InnerGenerate(WriterGenerationContext context)
        {
            Variable value;

            if (type.IsValueType)
            {
                var valueLocal = context.Generator.DeclareLocal(type);
                context.Generator.Emit(OpCodes.Ldarg_1);
                context.Generator.Emit(OpCodes.Unbox_Any, type);
                context.Generator.StoreLocalValueFromStack(valueLocal);

                value = new Variable(valueLocal);
            }
            else
            {
                value = new Variable(1);
            }

            var objectForSurrogatesIndex = objectsForSurrogates == null ? -1 : objectsForSurrogates.FindMatchingIndex(type);

            context.PushPrimitiveWriterOntoStack();
            context.Generator.PushIntegerOntoStack(objectForSurrogatesIndex != -1 ? 1 : 0);
            context.Generator.Call <PrimitiveWriter>(x => x.Write(false));

            if (objectForSurrogatesIndex != -1)
            {
                context.PushObjectWriterOntoStack();
                context.Generator.Emit(OpCodes.Dup);
                context.Generator.PushFieldValueOntoStack <ObjectWriter, SwapList>(x => x.objectsForSurrogates);
                context.Generator.PushIntegerOntoStack(objectForSurrogatesIndex);
                context.Generator.Call <SwapList>(x => x.GetByIndex(0));

                var delegateType = typeof(Func <,>).MakeGenericType(type, typeof(object));
                context.Generator.Emit(OpCodes.Castclass, delegateType);
                context.Generator.Emit(OpCodes.Ldarg_1);
                context.Generator.Emit(OpCodes.Call, delegateType.GetMethod("Invoke"));

                // here should be a primitive writer on a stack
                context.Generator.Call <object>(x => x.GetType());
                context.Generator.Call <ObjectWriter>(x => x.TouchAndWriteTypeId(typeof(void)));
                context.Generator.Emit(OpCodes.Pop);
            }

            if (WriteMethodGenerator.GenerateTryWriteObjectInline(context, generatePreSerializationCallback, generatePostSerializationCallback, value, type))
            {
                context.PushObjectWriterOntoStack();
                context.Generator.PushFieldValueOntoStack <ObjectWriter, HashSet <int> >(x => x.objectsWrittenInline);
                context.Generator.Emit(OpCodes.Ldarg_2); // reference identifier
                context.Generator.Call <HashSet <int> >(x => x.Add(0));
                context.Generator.Emit(OpCodes.Pop);
            }

            return(true);
        }
        private Action<ObjectWriter, PrimitiveWriter, object> PrepareWriteMethod(Type actualType, int surrogateId)
        {
            if(surrogateId == -1)
            {
                var specialWrite = LinkSpecialWrite(actualType);
                if(specialWrite != null)
                {
                    // linked methods are not added to writeMethodCache, there's no point
                    return specialWrite;
                }
            }

            if(!isGenerating)
            {
                if(surrogateId != -1)
                {
                    return (ow, pw, o) => ow.InvokeCallbacksAndWriteObject(surrogatesForObjects.GetByIndex(surrogateId).DynamicInvoke(new [] { o }));
                }
                return WriteObjectUsingReflection;
            }

            var method = new WriteMethodGenerator(actualType, treatCollectionAsUserObject, surrogateId,
                Helpers.GetFieldInfo<ObjectWriter, SwapList>(x => x.surrogatesForObjects),
                Helpers.GetMethodInfo<ObjectWriter>(x => x.InvokeCallbacksAndWriteObject(null))).Method;
            var result = (Action<ObjectWriter, PrimitiveWriter, object>)method.CreateDelegate(typeof(Action<ObjectWriter, PrimitiveWriter, object>));
            return result;
        }