コード例 #1
0
        /// <summary>
        /// An opportunity to clear an instance before caching it for future reuse as a cloning or deserialization target.
        /// The method is expected to call Serializer.Clear on all reference-type fields.
        /// </summary>
        /// <param name="target">The instance to clear.</param>
        /// <param name="context">A context object containing accumulated type mappings and object references.</param>
        public override void Clear(ref T target, SerializationContext context)
        {
            // null?
            if (target == null)
            {
                return;
            }

            // is it an object that we have already seen?
            int id;

            if (context.GetOrAddSerializedObjectId(target, out id))
            {
                target = (T)context.GetDeserializedObject(id);
                return;
            }

            // is it a polymorphic object?
            Type instanceType = target.GetType();

            if (typeof(T) != instanceType)
            {
                // determine and use the correct serialization handler based on the runtime type
                object objTarget = target;
                Serializer.Clear(instanceType, ref objTarget, context);
                target = (T)objTarget;
            }
            else
            {
                // call the serializer to clear the fields
                this.InnerClear(ref target, context);
            }
        }
コード例 #2
0
        /// <summary>
        /// Creates a deep clone of the given object.
        /// </summary>
        /// <param name="instance">The instance to clone.</param>
        /// <param name="target">An optional existing instance to clone into.</param>
        /// <param name="context">A context object containing accumulated type and object references.</param>
        public override void Clone(T instance, ref T target, SerializationContext context)
        {
            // null?
            if (instance == null)
            {
                target = instance;
                return;
            }

            // is it an object that we have already seen?
            int id;

            if (context.GetOrAddSerializedObjectId(instance, out id))
            {
                // find and reuse the object that we have already cloned in the object cache
                target = (T)context.GetDeserializedObject(id);
                if (target == null)
                {
                    throw new InvalidDataException("The serializer detected a circular reference: " + typeof(T));
                }

                return;
            }

            // did we use this target before? If so, we can't use it again.
            if (target != null && context.ContainsDeserializedObject(target))
            {
                target = default(T);
            }

            // is it a polymorphic object?
            Type instanceType = instance.GetType();

            if (typeof(T) != instanceType)
            {
                // determine and use the correct serialization handler based on the runtime type
                object objTarget = target;
                Serializer.Clone(instanceType, instance, ref objTarget, context);
                target = (T)objTarget;
            }
            else
            {
                // not polymorphic, invoke the serializer to clone the fields
                this.InnerClone(instance, ref target, context);
            }

            return;
        }
コード例 #3
0
        // serialize the ref envelope (null, duplicate reference, circular reference, polymorphism), before serializing the object itself
        public override void Serialize(BufferWriter writer, T instance, SerializationContext context)
        {
            // if null, just write the null prefix and exit
            if (instance == null)
            {
                writer.Write(RefPrefixNull);
                return;
            }

            // is it an object that we already serialized?
            int id;

            if (context.GetOrAddSerializedObjectId(instance, out id))
            {
                // write the reference id and don't serialize it again
                var prefix = RefPrefixExisting | id;
                writer.Write((uint)prefix);
                return;
            }

            // is it a polymorphic object?
            Type instanceType = instance.GetType();

            if (typeof(T) != instanceType)
            {
                // find the correct serialization handler
                var handler   = Serializer.GetHandler(instanceType, context);
                var handlerId = ((SerializationHandler)handler).Id;

                // let the context know that this type is required for deserialization
                context.PublishPolymorphicType(handlerId, instanceType);

                // write the type id before serializing the object
                var prefix = RefPrefixTyped | handlerId;
                writer.Write((uint)prefix);

                // delegate serialization to the correct serialization handler
                handler.UntypedSerialize(writer, instance, context);
                return;
            }

            // this is a new object, so invoke the serializer to persist its fields
            writer.Write(RefPrefixNew);
            this.innerSerializer.Serialize(writer, instance, context);
        }