private ILDelegateBuilder <SerializationManager.DeepCopier> EmitCopier(Type type, List <FieldInfo> fields)
        {
            var il = new ILDelegateBuilder <SerializationManager.DeepCopier>(
                FieldBuilder,
                type.Name + "DeepCopier",
                SerializationMethodInfos,
                SerializationMethodInfos.DeepCopierDelegate);

            // Declare local variables.
            var result     = il.DeclareLocal(type);
            var typedInput = il.DeclareLocal(type);

            // Set the typed input variable from the method parameter.
            il.LoadArgument(0);
            il.CastOrUnbox(type);
            il.StoreLocal(typedInput);

            // Construct the result.
            il.CreateInstance(type, result);

            // Record the object.
            il.LoadArgument(1);   // Load 'context' parameter.
            il.LoadArgument(0);   // Load 'original' parameter.
            il.LoadLocal(result); // Load 'result' local.
            il.BoxIfValueType(type);
            il.Call(SerializationMethodInfos.RecordObjectWhileCopying);

            // Copy each field.
            foreach (var field in fields)
            {
                // Load the field.
                il.LoadLocalAsReference(type, result);
                il.LoadLocal(typedInput);
                il.LoadField(field);

                // Deep-copy the field if needed, otherwise just leave it as-is.
                if (!field.FieldType.IsOrleansShallowCopyable())
                {
                    var copyMethod = SerializationMethodInfos.DeepCopyInner;

                    il.BoxIfValueType(field.FieldType);
                    il.LoadArgument(1);
                    il.Call(copyMethod);
                    il.CastOrUnbox(field.FieldType);
                }

                // Store the copy of the field on the result.
                il.StoreField(field);
            }

            il.LoadLocal(result);
            il.BoxIfValueType(type);
            il.Return();
            return(il);
        }
Esempio n. 2
0
        private ILDelegateBuilder <SerializationManager.Deserializer> EmitDeserializer(Type type, List <FieldInfo> fields)
        {
            var il = new ILDelegateBuilder <SerializationManager.Deserializer>(
                FieldBuilder,
                type.Name + "Deserializer",
                SerializationMethodInfos.DeserializerDelegate);

            // Declare local variables.
            var result = il.DeclareLocal(type);

            // Construct the result.
            il.CreateInstance(type, result, SerializationMethodInfos.GetUninitializedObject);

            // Record the object.
            il.LoadArgument(1); // Load the 'context' parameter.
            il.LoadLocal(result);
            il.BoxIfValueType(type);
            il.Call(SerializationMethodInfos.RecordObjectWhileDeserializing);

            // Deserialize each field.
            foreach (var field in fields)
            {
                // Deserialize the field.
                SimpleTypeSerializer serializer;
                var fieldType = field.FieldType.GetTypeInfo();
                if (fieldType.IsEnum)
                {
                    var typeHandle = fieldType.GetEnumUnderlyingType().TypeHandle;
                    il.LoadLocalAsReference(type, result);

                    il.LoadArgument(1);
                    il.Call(SerializationMethodInfos.GetStreamFromDeserializationContext);
                    il.Call(DirectSerializers[typeHandle].ReadMethod);
                    il.StoreField(field);
                }
                else if (DirectSerializers.TryGetValue(field.FieldType.TypeHandle, out serializer))
                {
                    il.LoadLocalAsReference(type, result);
                    il.LoadArgument(1);
                    il.Call(SerializationMethodInfos.GetStreamFromDeserializationContext);
                    il.Call(serializer.ReadMethod);

                    il.StoreField(field);
                }
                else
                {
                    var deserializeMethod = SerializationMethodInfos.DeserializeInner;

                    il.LoadLocalAsReference(type, result);
                    il.LoadType(field.FieldType);
                    il.LoadArgument(1);
                    il.Call(deserializeMethod);

                    // Store the value on the result.
                    il.CastOrUnbox(field.FieldType);
                    il.StoreField(field);
                }
            }

            il.LoadLocal(result);
            il.BoxIfValueType(type);
            il.Return();
            return(il);
        }
        private ILDelegateBuilder <Deserializer> EmitDeserializer(Type type, List <FieldInfo> fields,
                                                                  SerializationCallbacks callbacks)
        {
            var il = new ILDelegateBuilder <Deserializer>(
                FieldBuilder,
                type.Name + "Deserializer",
                SerializationMethodInfos.DeserializerDelegate);

            var streamingContext = default(ILDelegateBuilder <Deserializer> .Local);

            if (callbacks.OnDeserializing != null || callbacks.OnDeserialized != null)
            {
                streamingContext = il.DeclareLocal(typeof(StreamingContext));
                il.LoadLocalAddress(streamingContext);
                il.LoadConstant((int)StreamingContextStates.All);
                il.LoadArgument(1);
                il.Call(typeof(StreamingContext).GetConstructor(new[]
                                                                { typeof(StreamingContextStates), typeof(object) }));
            }

            // Declare local variables.
            var result = il.DeclareLocal(type);

            // Construct the result.
            il.CreateInstance(type, result, SerializationMethodInfos.GetUninitializedObject);

            // Record the object.
            il.LoadArgument(1); // Load the 'context' parameter.
            il.LoadLocal(result);
            il.BoxIfValueType(type);
            il.Call(SerializationMethodInfos.RecordObjectWhileDeserializing);

            if (callbacks.OnDeserializing != null)
            {
                il.LoadLocalAsReference(type, result);
                il.LoadLocal(streamingContext);
                il.Call(callbacks.OnDeserializing);
            }

            // Deserialize each field.
            foreach (var field in fields)
            {
                // Deserialize the field.
                var fieldType = field.FieldType;
                if (fieldType.IsEnum)
                {
                    var typeHandle = fieldType.GetEnumUnderlyingType().TypeHandle;
                    il.LoadLocalAsReference(type, result);

                    il.LoadArgument(1);
                    il.Call(SerializationMethodInfos.GetStreamFromDeserializationContext);
                    il.Call(DirectSerializers[typeHandle].ReadMethod);
                    il.StoreField(field);
                }
                else if (DirectSerializers.TryGetValue(field.FieldType.TypeHandle, out var serializer))
                {
                    il.LoadLocalAsReference(type, result);
                    il.LoadArgument(1);
                    il.Call(SerializationMethodInfos.GetStreamFromDeserializationContext);
                    il.Call(serializer.ReadMethod);

                    il.StoreField(field);
                }
                else
                {
                    var deserializeMethod = SerializationMethodInfos.DeserializeInner;

                    il.LoadLocalAsReference(type, result);
                    il.LoadType(field.FieldType);
                    il.LoadArgument(1);
                    il.Call(deserializeMethod);

                    // Store the value on the result.
                    il.CastOrUnbox(field.FieldType);
                    il.StoreField(field);
                }
            }

            if (callbacks.OnDeserialized != null)
            {
                il.LoadLocalAsReference(type, result);
                il.LoadLocal(streamingContext);
                il.Call(callbacks.OnDeserialized);
            }

            // If the type implements the IOnDeserialized lifecycle handler, call that method now.
            if (typeof(IOnDeserialized).IsAssignableFrom(type))
            {
                il.LoadLocalAsReference(type, result);
                il.LoadArgument(1);
                var concreteMethod = GetConcreteMethod(
                    type,
                    TypeUtils.Method((IOnDeserialized i) => i.OnDeserialized(default(ISerializerContext))));
                il.Call(concreteMethod);
            }

            // If the type implements the IDeserializationCallback lifecycle handler, call that method now.
            if (typeof(IDeserializationCallback).IsAssignableFrom(type))
            {
                il.LoadLocalAsReference(type, result);
                il.LoadArgument(1);

                var concreteMethod = GetConcreteMethod(
                    type,
                    TypeUtils.Method((IDeserializationCallback i) => i.OnDeserialization(default(object))));
                il.Call(concreteMethod);
            }

            il.LoadLocal(result);
            il.BoxIfValueType(type);
            il.Return();
            return(il);
        }