private static void GenerateInvokeCallbacksAndExecute(WriterGenerationContext context, bool generatePreSerializationCallback, bool generatePostSerializationCallback, Variable valueLocal, Type type, Action <WriterGenerationContext> bodyBuilder) { if (generatePreSerializationCallback || generatePostSerializationCallback) { context.Generator.BeginExceptionBlock(); } if (generatePreSerializationCallback) { context.PushObjectWriterOntoStack(); context.Generator.PushFieldValueOntoStack <ObjectWriter, Action <object> >(x => x.preSerializationCallback); context.Generator.PushVariableOntoStack(valueLocal); context.Generator.Call <Action <object> >(x => x.Invoke(null)); } bodyBuilder(context); if (generatePreSerializationCallback || generatePostSerializationCallback) { context.Generator.BeginFinallyBlock(); } if (generatePostSerializationCallback) { context.PushObjectWriterOntoStack(); context.Generator.PushFieldValueOntoStack <ObjectWriter, Action <object> >(x => x.postSerializationCallback); context.Generator.PushVariableOntoStack(valueLocal); context.Generator.Call <Action <object> >(x => x.Invoke(null)); } if (generatePreSerializationCallback || generatePostSerializationCallback) { context.Generator.EndExceptionBlock(); } }
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 static void GenerateWriteDelegate(WriterGenerationContext context, Variable valueLocal) { var array = context.Generator.DeclareLocal(typeof(Delegate[])); var loopLength = context.Generator.DeclareLocal(typeof(int)); var element = context.Generator.DeclareLocal(typeof(Delegate)); var delegateTargetLocal = context.Generator.DeclareLocal(typeof(object)); var delegateTargetVariable = new Variable(delegateTargetLocal); context.PushPrimitiveWriterOntoStack(); context.PushObjectWriterOntoStack(); context.Generator.PushVariableOntoStack(valueLocal); context.Generator.Call <ObjectWriter>(x => x.GetDelegatesWithNonTransientTargets(null)); context.Generator.Emit(OpCodes.Castclass, typeof(Delegate[])); context.Generator.Emit(OpCodes.Dup); context.Generator.StoreLocalValueFromStack(array); // array refrence should be on the top of stack here context.Generator.Emit(OpCodes.Ldlen); context.Generator.Emit(OpCodes.Dup); context.Generator.StoreLocalValueFromStack(loopLength); // primitive writer should be on the stack // array length should be on the stack context.Generator.Call <PrimitiveWriter>(x => x.Write(0)); GeneratorHelper.GenerateLoop(context, loopLength, c => { context.Generator.PushLocalValueOntoStack(array); context.Generator.PushLocalValueOntoStack(c); context.Generator.Emit(OpCodes.Ldelem, element.LocalType); context.Generator.Emit(OpCodes.Dup); context.Generator.StoreLocalValueFromStack(element); // element reference should be on the stack context.Generator.PushPropertyValueOntoStack <MulticastDelegate, object>(x => x.Target); context.Generator.StoreLocalValueFromStack(delegateTargetLocal); GenerateWriteDeferredReference(context, delegateTargetVariable, typeof(object)); context.PushObjectWriterOntoStack(); context.Generator.PushPropertyValueOntoStack <ObjectWriter, IdentifiedElementsDictionary <MethodDescriptor> >(x => x.Methods); context.Generator.PushLocalValueOntoStack(element); context.Generator.PushPropertyValueOntoStack <MulticastDelegate, MethodInfo>(x => x.Method); context.Generator.Emit(OpCodes.Newobj, Helpers.GetConstructorInfo <MethodDescriptor>(typeof(MethodInfo))); context.Generator.Call <IdentifiedElementsDictionary <MethodDescriptor> >(x => x.TouchAndWriteId(null)); context.Generator.Emit(OpCodes.Pop); }); }
private void GenerateAddCallbackToInvokeList(WriterGenerationContext context, LocalBuilder valueLocal, Type actualType, Type attributeType) { var actionCtor = typeof(Action).GetConstructor(new[] { typeof(object), typeof(IntPtr) }); var addToListMethod = Helpers.GetMethodInfo <List <Action> >(x => x.Add(null)); var methodsWithAttribute = Helpers.GetMethodsWithAttribute(attributeType, actualType).ToList(); var count = methodsWithAttribute.Count; if (count > 0) { context.PushObjectWriterOntoStack(); context.Generator.PushFieldValueOntoStack <ObjectWriter, List <Action> >(x => x.postSerializationHooks); } for (var i = 1; i < count; i++) { context.Generator.Emit(OpCodes.Dup); } foreach (var method in methodsWithAttribute) { // let's make the delegate if (method.IsStatic) { context.Generator.Emit(OpCodes.Ldnull); } else { context.Generator.PushLocalValueOntoStack(valueLocal); } context.Generator.Emit(OpCodes.Ldftn, method); context.Generator.Emit(OpCodes.Newobj, actionCtor); // and add it to invoke list context.Generator.Emit(OpCodes.Call, addToListMethod); } }
internal static void GenerateWriteDeferredReference(WriterGenerationContext context, Variable valueLocal, Type formalType) { var finish = context.Generator.DefineLabel(); var isNotNull = context.Generator.DefineLabel(); var isNotTransient = context.Generator.DefineLabel(); context.Generator.PushVariableOntoStack(valueLocal); context.Generator.Emit(OpCodes.Brtrue_S, isNotNull); context.PushNullReferenceOnStack(); context.Generator.Emit(OpCodes.Br, finish); context.Generator.MarkLabel(isNotNull); var formalTypeIsActualType = (formalType.Attributes & TypeAttributes.Sealed) != 0; if (!formalTypeIsActualType) { context.Generator.PushVariableOntoStack(valueLocal); context.Generator.Call(() => Helpers.IsTransient((object)null)); context.Generator.Emit(OpCodes.Brfalse_S, isNotTransient); context.PushNullReferenceOnStack(); context.Generator.Emit(OpCodes.Br, finish); context.Generator.MarkLabel(isNotTransient); context.PushObjectWriterOntoStack(); context.Generator.PushVariableOntoStack(valueLocal); context.Generator.Call <ObjectWriter>(x => x.WriteDeferredReference(null)); } else { if (Helpers.IsTransient(formalType)) { context.PushNullReferenceOnStack(); } else { context.PushObjectWriterOntoStack(); context.Generator.PushVariableOntoStack(valueLocal); context.Generator.Call <ObjectWriter>(x => x.WriteDeferredReference(null)); } } context.Generator.MarkLabel(finish); }
protected override bool InnerGenerate(WriterGenerationContext context) { var surrogateId = surrogatesForObjects.FindMatchingIndex(type); if (surrogateId == -1) { return(false); } var objVariable = new Variable(1); context.PushObjectWriterOntoStack(); context.Generator.PushFieldValueOntoStack <ObjectWriter, SwapList>(x => x.surrogatesForObjects); context.Generator.PushIntegerOntoStack(surrogateId); context.Generator.Call <SwapList>(x => x.GetByIndex(0)); // call surrogate factory to obtain surrogate object var delegateType = typeof(Func <,>).MakeGenericType(type, typeof(object)); context.Generator.Emit(OpCodes.Castclass, delegateType); context.Generator.PushVariableOntoStack(objVariable); if (type.IsValueType) { context.Generator.Emit(OpCodes.Unbox_Any, type); } context.Generator.Emit(OpCodes.Call, delegateType.GetMethod("Invoke")); context.Generator.StoreVariableValueFromStack(objVariable); context.PushObjectWriterOntoStack(); context.Generator.PushFieldValueOntoStack <ObjectWriter, ObjectIdentifier>(x => x.identifier); context.Generator.PushVariableOntoStack(objVariable); // object reference context.Generator.Emit(OpCodes.Ldarg_2); // reference id context.Generator.Call <ObjectIdentifier>(x => x.SetIdentifierForObject(null, 0)); context.Generator.PushVariableOntoStack(objVariable); return(true); }
protected override bool InnerGenerate(WriterGenerationContext context) { var result = false; var methods = Helpers.GetMethodsWithAttribute(typeof(PostSerializationAttribute), type).ToArray(); foreach (var method in methods) { if (!method.IsStatic) { context.Generator.Emit(OpCodes.Ldarg_1); context.Generator.Emit(OpCodes.Castclass, method.ReflectedType); } if (method.IsVirtual) { context.Generator.Emit(OpCodes.Callvirt, method); } else { context.Generator.Emit(OpCodes.Call, method); } result = true; } methods = Helpers.GetMethodsWithAttribute(typeof(LatePostSerializationAttribute), type).ToArray(); foreach (var method in methods) { context.PushObjectWriterOntoStack(); context.Generator.PushFieldValueOntoStack <ObjectWriter, List <Action> >(x => x.postSerializationHooks); context.Generator.PushTypeOntoStack(typeof(Action)); if (method.IsStatic) { context.Generator.Emit(OpCodes.Ldnull); } else { context.Generator.Emit(OpCodes.Ldarg_1); context.Generator.Emit(OpCodes.Castclass, method.ReflectedType); } context.Generator.Emit(OpCodes.Ldtoken, method); if (method.DeclaringType.IsGenericType) { context.Generator.Emit(OpCodes.Ldtoken, method.DeclaringType); context.Generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <object, MethodBase>(x => MethodBase.GetMethodFromHandle(new RuntimeMethodHandle(), new RuntimeTypeHandle()))); } else { context.Generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <object, MethodBase>(x => MethodBase.GetMethodFromHandle(new RuntimeMethodHandle()))); } context.Generator.Emit(OpCodes.Castclass, typeof(MethodInfo)); context.Generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <object, Delegate>(x => Delegate.CreateDelegate(null, null, method))); context.Generator.Emit(OpCodes.Castclass, typeof(Action)); context.Generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <List <Action> >(x => x.Add(null))); result = true; } return(result); }