/// <summary>
        /// Deserialize a user type instance from a POF stream by reading its
        /// state using the specified <see cref="IPofReader"/> object.
        /// </summary>
        /// <remarks>
        /// An implementation of <b>IPofSerializer</b> is required to follow
        /// the following steps in sequence for reading in an object of a
        /// user type:
        /// <list type="number">
        /// <item>
        /// <description>
        /// If the object is evolvable, the implementation must get the
        /// version by calling <see cref="IPofReader.VersionId"/>.
        /// </description>
        /// </item>
        /// <item>
        /// <description>
        /// The implementation may read any combination of the
        /// properties of the user type by using "read" methods of the
        /// <b>IPofReader</b>, but it must do so in the order of the property
        /// indexes. Additionally, the implementation must call
        /// {@link IPofReader#RegisterIdentity} with the new instance prior
        /// to reading any properties which are user type instances
        /// themselves.
        /// </description>
        /// </item>
        /// <item>
        /// <description>
        /// After all desired properties of the user type have been read,
        /// the implementation must terminate the reading of the user type by
        /// calling <see cref="IPofReader.ReadRemainder"/>.
        /// </description>
        /// </item>
        /// </list>
        /// </remarks>
        /// <param name="pofReader">
        /// The <b>IPofReader</b> with which to read the object's state.
        /// </param>
        /// <returns>
        /// The deserialized user type instance.
        /// </returns>
        /// <exception cref="IOException">
        /// If an I/O error occurs.
        /// </exception>
        public Object Deserialize(IPofReader pofReader)
        {
            try
            {
                IPortableObject po = (IPortableObject)
                                     Activator.CreateInstance(GetTypeForTypeId(pofReader.PofContext, m_nTypeId));

                CacheFactory.Log("Deserializing " + po.GetType(), CacheFactory.LogLevel.Max);

                bool             fEvolvable = po is IEvolvableObject;
                IEvolvableObject et         = fEvolvable ? (IEvolvableObject)po : null;

                int typeId = ((PofStreamReader.UserTypeReader)pofReader).NextPropertyIndex;
                while (typeId > 0)
                {
                    IEvolvable e      = null;
                    IPofReader reader = pofReader.CreateNestedPofReader(typeId);

                    if (fEvolvable)
                    {
                        e             = et.GetEvolvable(typeId);
                        e.DataVersion = reader.VersionId;
                    }

                    po.ReadExternal(reader);

                    Binary binRemainder = reader.ReadRemainder();
                    if (fEvolvable)
                    {
                        e.FutureData = binRemainder;
                    }
                    typeId = ((PofStreamReader.UserTypeReader)pofReader).NextPropertyIndex;
                }

                pofReader.ReadRemainder();
                return(po);
            }
            catch (Exception e)
            {
                String sClass = null;
                try
                {
                    sClass = pofReader.PofContext.GetTypeName(m_nTypeId);
                }
                catch (Exception)
                {
                }

                throw new IOException(
                          "An exception occurred instantiating a IPortableObject"
                          + " user type from a POF stream: type-id=" + m_nTypeId
                          + (sClass == null ? "" : ", class-name=" + sClass)
                          + ", exception=\n" + e, e);
            }
        }
        /// <summary>
        /// Initialize the specified (newly instantiated) PortableObject instance
        /// using the specified reader.
        /// </summary>
        /// <param name="portable">The object to initialize.</param>
        /// <param name="reader">
        /// The PofReader with which to read the object's state.
        /// </param>
        public void Initialize(IPortableObject portable, IPofReader reader)
        {
            // set the version identifier
            bool       isEvolvable = portable is IEvolvable;
            IEvolvable evolvable   = null;

            if (isEvolvable)
            {
                evolvable             = (IEvolvable)portable;
                evolvable.DataVersion = reader.VersionId;
            }

            // read the object's properties
            portable.ReadExternal(reader);

            // read any future properties
            Binary remainder = reader.ReadRemainder();

            if (isEvolvable)
            {
                evolvable.FutureData = remainder;
            }
        }