public static bool TryFillBody(ILGenerator generator, Type type, bool treatCollectionAsUserObject, Action <ILGenerator> beforeCreationAction = null) { var creationWay = ObjectReader.GetCreationWay(type, treatCollectionAsUserObject); if (creationWay == ObjectReader.CreationWay.Null) { return(false); } if (beforeCreationAction != null) { beforeCreationAction(generator); } generator.PushTypeOntoStack(type); switch (creationWay) { case ObjectReader.CreationWay.DefaultCtor: generator.Call(() => Activator.CreateInstance(type)); break; case ObjectReader.CreationWay.Uninitialized: generator.Call(() => FormatterServices.GetUninitializedObject(type)); break; } return(true); }
private void GenerateTouchObject(Type formalType) { var objectIdLocal = generator.DeclareLocal(typeof(Int32)); var objectTypeLocal = generator.DeclareLocal(typeof(Type)); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Stloc, objectIdLocal); PushTypeOntoStack(formalType); generator.Emit(OpCodes.Stloc, objectTypeLocal); switch (ObjectReader.GetCreationWay(formalType)) { case ObjectReader.CreationWay.Null: break; case ObjectReader.CreationWay.DefaultCtor: // execute if <<localId>> was not found in DOC PushDeserializedObjectsCollectionOntoStack(); generator.Emit(OpCodes.Ldloc, objectIdLocal); // first argument generator.Emit(OpCodes.Ldloc, objectTypeLocal); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo(() => Activator.CreateInstance(typeof(void)))); // second argument generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <AutoResizingList <object> >(x => x.SetItem(0, new object()))); break; case ObjectReader.CreationWay.Uninitialized: // execute if <<localId>> was not found in DOC PushDeserializedObjectsCollectionOntoStack(); generator.Emit(OpCodes.Ldloc, objectIdLocal); // first argument //PushTypeOntoStack(formalType); generator.Emit(OpCodes.Ldloc, objectTypeLocal); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo(() => FormatterServices.GetUninitializedObject(typeof(void)))); // second argument generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <AutoResizingList <object> >(x => x.SetItem(0, new object()))); break; } }
private static void GenerateReadObjectInner(ReaderGenerationContext context, Type formalType) { var objectIdLocal = context.Generator.DeclareLocal(typeof(int)); context.PushObjectIdOntoStack(); context.Generator.StoreLocalValueFromStack(objectIdLocal); GenerateTouchObject(context, formalType); switch (ObjectReader.GetCreationWay(formalType, context.TreatCollectionAsUserObject)) { case ObjectReader.CreationWay.Null: GenerateReadNotPrecreated(context, formalType, objectIdLocal); break; case ObjectReader.CreationWay.DefaultCtor: GenerateUpdateElements(context, formalType, objectIdLocal); break; case ObjectReader.CreationWay.Uninitialized: GenerateUpdateFields(context, formalType, objectIdLocal); break; } }
private void GenerateReadObjectInner(Type formalType) { var finish = generator.DefineLabel(); var objectIdLocal = generator.DeclareLocal(typeof(Int32)); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Stloc, objectIdLocal); GenerateTouchObject(formalType); switch (ObjectReader.GetCreationWay(formalType)) { case ObjectReader.CreationWay.Null: GenerateReadNotPrecreated(formalType, objectIdLocal); break; case ObjectReader.CreationWay.DefaultCtor: GenerateUpdateElements(formalType, objectIdLocal); break; case ObjectReader.CreationWay.Uninitialized: GenerateUpdateFields(formalType, objectIdLocal); break; } PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Brfalse, finish); PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldloc, objectIdLocal); GenerateCodeCall <object, ObjectReader, int>((obj, or, objectId) => { Helpers.SwapObjectWithSurrogate(ref obj, or.objectsForSurrogates); or.deserializedObjects[objectId] = obj; // could be swapped }); var methods = Helpers.GetMethodsWithAttribute(typeof(PostDeserializationAttribute), formalType); foreach (var method in methods) { PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Castclass, method.ReflectedType); generator.Emit(OpCodes.Call, method); } methods = Helpers.GetMethodsWithAttribute(typeof(LatePostDeserializationAttribute), formalType); foreach (var method in methods) { generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, Helpers.GetFieldInfo <ObjectReader, object>(or => or.postDeserializationHooks)); PushTypeOntoStack(typeof(Action)); if (method.IsStatic) { generator.Emit(OpCodes.Ldnull); } else { PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Castclass, method.ReflectedType); } generator.Emit(OpCodes.Ldtoken, method); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <object, MethodBase>(x => MethodBase.GetMethodFromHandle(new RuntimeMethodHandle()))); generator.Emit(OpCodes.Castclass, typeof(MethodInfo)); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <object, Delegate>(x => Delegate.CreateDelegate(null, null, method))); generator.Emit(OpCodes.Castclass, typeof(Action)); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <List <Action> >(x => x.Add(null))); } generator.Emit(OpCodes.Ldarg_0); PushDeserializedObjectOntoStack(objectIdLocal); GenerateCodeCall <ObjectReader, object>((or, obj) => { if (or.postDeserializationCallback != null) { or.postDeserializationCallback(obj); } }); generator.MarkLabel(finish); }
private void GenerateReadObjectInner(Type formalType) { var finish = generator.DefineLabel(); var objectIdLocal = generator.DeclareLocal(typeof(Int32)); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Stloc, objectIdLocal); GenerateTouchObject(formalType); switch (ObjectReader.GetCreationWay(formalType, treatCollectionAsUserObject)) { case ObjectReader.CreationWay.Null: GenerateReadNotPrecreated(formalType, objectIdLocal); break; case ObjectReader.CreationWay.DefaultCtor: GenerateUpdateElements(formalType, objectIdLocal); break; case ObjectReader.CreationWay.Uninitialized: GenerateUpdateFields(formalType, objectIdLocal); break; } PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Brfalse, finish); var methods = Helpers.GetMethodsWithAttribute(typeof(PostDeserializationAttribute), formalType).ToArray(); foreach (var method in methods) { PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Castclass, method.ReflectedType); if (method.IsVirtual) { generator.Emit(OpCodes.Callvirt, method); } else { generator.Emit(OpCodes.Call, method); } } methods = Helpers.GetMethodsWithAttribute(typeof(LatePostDeserializationAttribute), formalType).ToArray(); if (objectForSurrogateId != -1 && methods.Length != 0) { throw new InvalidOperationException( string.Format(ObjectReader.LateHookAndSurrogateError, formalType)); } foreach (var method in methods) { generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, postDeserializationHooksField); PushTypeOntoStack(typeof(Action)); if (method.IsStatic) { generator.Emit(OpCodes.Ldnull); } else { PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Castclass, method.ReflectedType); } generator.Emit(OpCodes.Ldtoken, method); if (method.DeclaringType.IsGenericType) { generator.Emit(OpCodes.Ldtoken, method.DeclaringType); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <object, MethodBase>(x => MethodBase.GetMethodFromHandle(new RuntimeMethodHandle(), new RuntimeTypeHandle()))); } else { generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <object, MethodBase>(x => MethodBase.GetMethodFromHandle(new RuntimeMethodHandle()))); } generator.Emit(OpCodes.Castclass, typeof(MethodInfo)); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <object, Delegate>(x => Delegate.CreateDelegate(null, null, method))); generator.Emit(OpCodes.Castclass, typeof(Action)); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <List <Action> >(x => x.Add(null))); } var callbackLocal = generator.DeclareLocal(typeof(Action <object>)); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, postDeserializationCallbackField); // PROMPT var afterCallbackCall = generator.DefineLabel(); generator.Emit(OpCodes.Dup); generator.Emit(OpCodes.Stloc, callbackLocal); generator.Emit(OpCodes.Brfalse, afterCallbackCall); //generator.Emit(OpCodes.Castclass, typeof(Action<object>)); generator.Emit(OpCodes.Ldloc, callbackLocal); PushDeserializedObjectOntoStack(objectIdLocal); //generator.Emit(OpCodes.Ldnull); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <Action <object> >(x => x.Invoke(null))); generator.MarkLabel(afterCallbackCall); // surrogates if (objectForSurrogateId != -1) { // used (1) generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, deserializedObjectsField); generator.Emit(OpCodes.Ldloc, objectIdLocal); // obtain surrogate factory generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, objectsForSurrogatesField); generator.Emit(OpCodes.Ldc_I4, objectForSurrogateId); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <InheritanceAwareList <Delegate> >(x => x.GetByIndex(0))); // recreate an object from the surrogate var delegateType = typeof(Func <,>).MakeGenericType(formalType, typeof(object)); generator.Emit(OpCodes.Castclass, delegateType); PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Call, delegateType.GetMethod("Invoke")); // save recreated object // (1) here generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <AutoResizingList <object> >(x => x.SetItem(0, null))); } generator.MarkLabel(finish); }