示例#1
0
        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);
        }
示例#2
0
        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;
            }
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }