void SerializeAutoSerializable(object instance, TypeSerializationArgs args)
        {
            TypeSerializationArgs callerArgs = args;

            args = args.Clone();

            if (this.IsInline)
            {
                //  Inline objects are serialized with only a 2-byte length prefix
                //  No version info or anything else
                int  length         = 0;
                long lengthPosition = args.Writer.BaseStream.Position;
                long endPosition    = -1;

                args.Writer.Write((byte)length);

                if (instance != null)
                {
                    args.Header                = new TypeSerializationHeader();
                    args.Header.DataVersion    = 1;
                    args.Header.DataMinVersion = 1;

                    this.autoSerializeMethod(instance, args);
                    endPosition = args.Writer.BaseStream.Position;

                    length = (int)((endPosition - lengthPosition) - InlineHeaderSize);
                    if (length > MaxInlineSize)
                    {
                        throw new NotSupportedException(string.Format(
                                                            "Inline classes must be {0} bytes or less. Class {1} serialized to {2} bytes.",
                                                            MaxInlineSize,
                                                            instance.GetType().FullName,
                                                            length
                                                            ));
                    }

                    args.Writer.BaseStream.Position = lengthPosition;
                    args.Writer.Write((byte)length);
                    args.Writer.BaseStream.Position = endPosition;
                }
            }
            else if (instance == null)
            {
                args.Writer.Write(NullVersion);
            }
            else
            {
                args.Header                = new TypeSerializationHeader();
                args.Header.DataVersion    = (byte)this.CurrentVersion;
                args.Header.DataMinVersion = (byte)this.MinVersion;

                //  If min version is less than or equal legacy version then write
                //  out legacy version + 1 as the min version in the data stream.This
                //  is to prevent older class definitions from attempting to
                //  deserialize the new data using IVersionSerializable
                if ((this.LegacyVersion > 0) && (this.LegacyVersion >= this.MinVersion))
                {
                    args.Header.DataMinVersion = (byte)(this.LegacyVersion + 1);
                }

                //  If this isn't a base class invocation then make sure
                //  SerializationInfo is initialized for the first time.
                //  If it is a base class then get the base class info
                //  from the parent's SerializationInfo
                if (callerArgs.IsBaseClass == false)
                {
                    ISerializationInfo info = instance as ISerializationInfo;

                    if (info != null)
                    {
                        args.SerializationInfo = info.SerializationInfo;
                    }
                    else
                    {
                        //  SerializationInfo may not be null in this case
                        //  because this may be an object contained in a parent
                        //  class. We need to make sure the child object doesn't
                        //  use the serialization info from the container
                        args.SerializationInfo = null;
                    }
                }
                else if (args.SerializationInfo != null)
                {
                    args.SerializationInfo = callerArgs.SerializationInfo.BaseClassInfo;
                }

                //  Handled cached serialization info if original data
                //  was newer than the class definition that deserialized it
                if (
                    (args.SerializationInfo != null) &&
                    (args.SerializationInfo.Version > this.CurrentVersion)
                    )
                {
                    args.Header.DataVersion    = (byte)args.SerializationInfo.Version;
                    args.Header.DataMinVersion = (byte)args.SerializationInfo.MinVersion;
                }

                //  Write a special version byte to indicate this serialized
                //  data uses a header. Because this version is guaranteed to
                //  be higher than actual object versions, older serialization
                //  code will simply treat this is a higher unhandled version,
                //  which is true.
                args.Writer.Write(HasHeaderVersion);

                //  Write the header with placeholder data
                args.Header.Write(args.Writer);

                //  Serialize the object
                this.autoSerializeMethod(instance, args);

                //  Update the header with final data. Note that the
                //  TypeSerializationHeader class takes care of the
                //  stream position
                args.Header.Write(args.Writer);
            }
        }
        bool DeserializeAutoSerializable(ref object instance, TypeSerializationArgs args)
        {
            byte dataVersion = 1;
            bool isSerializationInfoSupported = (instance == null) ? this.supportsSerializationInfo : (instance is ISerializationInfo);
            TypeSerializationArgs callerArgs  = args;
            byte dataMinVersion = 0;

            //  Create a local copy of args so we don't mess with caller's context
            args = args.Clone();

            if (this.IsInline)
            {
                //  Read length prefix. If length is 0 then object is null
                byte length = args.Reader.ReadByte();
                if (length == 0)
                {
                    dataVersion = NullVersion;
                }
            }
            else
            {
                dataVersion = args.Reader.ReadByte();
            }

            if (dataVersion == NullVersion)
            {
                instance = null;
                return(false);
            }

            if (dataVersion == HasHeaderVersion)
            {
                args.Header = new TypeSerializationHeader();
                args.Header.Read(args.Reader);
                dataVersion    = args.Header.DataVersion;
                dataMinVersion = args.Header.DataMinVersion;
            }

            if (
                //  Version of the data is less than our supported minimum version
                //	OR data is a lower version than the min version that can be deserialized
                //  OR data is a higher version but this type isn't forward compatible
                //  OR data has a min version that is higher than this current type definition
                (dataVersion < this.MinVersion) ||
                (this.CurrentVersion < dataMinVersion) ||
                (dataVersion < this.MinDeserializeVersion) ||
                ((dataVersion > this.CurrentVersion) && (isSerializationInfoSupported == false)) ||
                ((args.Header != null) && (args.Header.DataMinVersion > this.CurrentVersion))
                )
            {
                throw new UnhandledVersionException(this.CurrentVersion, dataVersion);
            }
            else
            {
                if (instance == null)
                {
                    instance = CreateInstance();
                }

                //  If this is the derived class then create a new top-level
                //  serialization info. If this is the base class then set
                //  the base class serialization info
                if (callerArgs.IsBaseClass == false)
                {
                    args.SerializationInfo = new SerializationInfo();

                    if (isSerializationInfoSupported == true)
                    {
                        ((ISerializationInfo)instance).SerializationInfo = args.SerializationInfo;
                    }
                }
                else
                {
                    callerArgs.SerializationInfo.BaseClassInfo = new SerializationInfo();
                    args.SerializationInfo = callerArgs.SerializationInfo.BaseClassInfo;
                }

                args.SerializationInfo.Version = dataVersion;

                if (args.Header != null)
                {
                    args.SerializationInfo.MinVersion = args.Header.DataMinVersion;
                }

                this.autoDeserializeMethod(instance, dataVersion, args);

                if (args.Succeeded == false)
                {
                    //this should never be hit, as it is a legacy of the volatile flag
                    return(false);
                }

                if (isSerializationInfoSupported == true)
                {
                    if (dataVersion > this.CurrentVersion)
                    {
                        int readDataLength      = (int)(args.Reader.BaseStream.Position - args.Header.DataPosition);
                        int unhandledDataLength = args.Header.DataLength - readDataLength;

                        args.SerializationInfo.UnhandledData = args.Reader.ReadBytes(unhandledDataLength);
                    }
                }
            }

            return(true);
        }