File: Serialization\Manager\ReachObjectContext.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\ReachFramework\ReachFramework.csproj (ReachFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
/*++
 
    Abstract:
        This file contains the implementation representing
        the context of a Serializable object. This woudl include
        information about the object itself and all the properties
        contained within that object
 
--*/
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Xml;
using System.IO;
using System.Security;
using System.ComponentModel.Design.Serialization;
using System.Windows.Xps.Packaging;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Markup;
 
namespace System.Windows.Xps.Serialization
{
    internal class SerializableObjectContext :
                   BasicContext
    {
        #region Constructor
 
        static
        SerializableObjectContext(
            )
        {
            _recycableSerializableObjectContexts = new Stack();
        }
 
 
        /// <summary>
        /// Instantiates an ObjectContext
        /// </summary>
        /// <param name="name">
        /// The name of type of the object.
        /// </param>
        /// <param name="prefix">
        /// The perfix (namespace) of the type of the object.
        /// </param>
        /// <param name="target">
        /// The instance of the object which contained this object as
        /// one of its properties.
        /// </param>
        /// <param name="serializablePropertyContext">
        /// The property from which this object was driven to serialization.
        /// </param>
        public
        SerializableObjectContext(
            string name,
            string prefix,
            object target,
            SerializablePropertyContext serializablePropertyContext
            ) :
        base(name, prefix)
        {
            //
            // Validate Input Arguments
            //
            ArgumentNullException.ThrowIfNull(target);
 
            _targetObject            = target;
            _isComplexValue          = false;
            _backingPropertyContext  = serializablePropertyContext;
        }
 
 
        /// <summary>
        ///     Instantiates an ObjectContext
        /// </summary>
        /// <param name="target">
        /// The instance of the object which contained this object as
        /// one of its properties.
        /// </param>
        /// <param name="serializablePropertyContext">
        /// The property from which this object was driven to serialization.
        /// </param>
        public
        SerializableObjectContext(
            object                      target,
            SerializablePropertyContext serializablePropertyContext
            )
        {
            Initialize(target, serializablePropertyContext);
        }
 
        #endregion Constructor
 
        #region Internal Methods
 
        /// <summary>
        /// Factory method to create ObjectContexts
        /// </summary>
        /// <param name="serializationManager">
        /// The manager controllig the serialization process.
        /// </param>
        /// <param name="serializableObject">
        /// The instance of the object which contained this object as
        /// one of its properties.
        /// </param>
        /// <param name="serializableObjectParentContext">
        /// The ObjectContext of the parent object of this object.
        /// </param>
        /// <param name="serializablePropertyContext">
        /// The property from which this object was driven to serialization.
        /// </param>
        internal
        static
        SerializableObjectContext
        CreateContext(
            PackageSerializationManager   serializationManager,
            object                      serializableObject,
            SerializableObjectContext   serializableObjectParentContext,
            SerializablePropertyContext serializablePropertyContext
            )
        {
            //
            // Check for element pre-existance to avoid infinite loops
            // in the process of serialization
            //
            int stackIndex = 0;
 
            object currentObject = null;
 
            for(currentObject = serializationManager.GraphContextStack[stackIndex];
                currentObject != null;
                currentObject = serializationManager.GraphContextStack[++stackIndex])
            {
                SerializableObjectContext currentObjectContext = currentObject as SerializableObjectContext;
 
                if(currentObjectContext!=null &&
                   currentObjectContext.TargetObject == serializableObject)
                {
                    throw new XpsSerializationException(SR.ReachSerialization_CycleDetectedInSerialization);
                }
            }
 
            SerializableObjectContext serializableObjectContext;
            lock (_stackLock)
            {
                serializableObjectContext =
                    _recycableSerializableObjectContexts.Count == 0 ?
                    null :
                    (SerializableObjectContext)_recycableSerializableObjectContexts.Pop();
            }
 
            if(serializableObjectContext == null)
            {
                serializableObjectContext = new SerializableObjectContext(serializableObject,
                                                                          serializablePropertyContext);
            }
            else
            {
                serializableObjectContext.Initialize(serializableObject,
                                                     serializablePropertyContext);
            }
 
            {
                //
                // Namespace related creation within the context
                //
                MetroSerializationNamespaceTable parentNamespaceTable =
                serializableObjectParentContext != null ? serializableObjectParentContext.NamespaceTable : null;
 
                if (serializableObjectContext.NamespaceTable == null)
                {
                    serializableObjectContext.NamespaceTable = new MetroSerializationNamespaceTable(parentNamespaceTable);
                }
            }
 
            {
                //
                // Properties related creation within the context
                //
                if(serializableObjectContext.PropertiesCollection == null)
                {
                    serializableObjectContext.PropertiesCollection = new  SerializablePropertyCollection(serializationManager,
                                                                                                         serializableObject);
                }
                else
                {
                    serializableObjectContext.PropertiesCollection.Initialize(serializationManager,
                                                                              serializableObject);
                }
            }
 
            serializableObjectContext.Name = serializableObjectContext.TargetObject.GetType().Name;
 
            return serializableObjectContext;
        }
 
        /// <summary>
        /// To optimize, we build a cache of created contexts
        /// and recycle them instead of desposing them.
        /// </summary>
        /// <param name="serializableObjectContext">
        /// Context to recycle.
        /// </param>
        internal
        static
        void
        RecycleContext(
            SerializableObjectContext   serializableObjectContext
            )
        {
            serializableObjectContext.Clear();
            lock (_stackLock)
            {
                _recycableSerializableObjectContexts.Push(serializableObjectContext);
            }
        }
 
        #endregion Internal Methods
 
 
        #region Public Properties
 
        /// <summary>
        /// Query target object
        /// </summary>
        public
        object
        TargetObject
        {
            get
            {
                return _targetObject;
            }
        }
 
        /// <summary>
        /// Query/Set namespace informaiton table
        /// </summary>
        public
        MetroSerializationNamespaceTable
        NamespaceTable
        {
            get
            {
                return _namespaceTable;
            }
 
            set
            {
                _namespaceTable = value;
            }
        }
 
 
        /// <summary>
        /// Query/Set the collection containing all
        /// the properties of the current object
        /// </summary>
        public
        SerializablePropertyCollection
        PropertiesCollection
        {
            get
            {
                return _propertiesCollection;
            }
            set
            {
                _propertiesCollection = value;
            }
        }
 
        /// <summary>
        /// Query/Set the type of the property / object being
        /// considered for serialization.
        /// </summary>
        public
        bool
        IsComplexValue
        {
            get
            {
                return _isComplexValue;
            }
 
            set
            {
                _isComplexValue = value;
            }
        }
 
 
        /// <summary>
        /// Query / Set the readability type of the object
        /// </summary>
        public
        bool
        IsReadOnlyValue
        {
            get
            {
                return _isReadOnlyValue;
            }
 
            set
            {
                _isReadOnlyValue = value;
            }
        }
 
        #endregion Public Properties
 
        #region Public Methods
 
 
        /// <summary>
        /// Initialize the context
        /// </summary>
        public
        void
        Initialize(
            object                      target,
            SerializablePropertyContext serializablePropertyContext
            )
        {
            Initialize();
            _targetObject           = target;
            _isComplexValue         = false;
            _backingPropertyContext = serializablePropertyContext;
 
            if(_backingPropertyContext!=null)
            {
                _isComplexValue  = _backingPropertyContext.IsComplex;
                _isReadOnlyValue = _backingPropertyContext.IsReadOnly;
            }
            else
            {
                _isComplexValue  = true;
                _isReadOnlyValue = false;
            }
        }
 
        /// <summary>
        /// Clear the Context
        /// </summary>
        public
        override
        void
        Clear()
        {
            _targetObject    = null;
            _isComplexValue  = false;
            _isReadOnlyValue = false;
            _namespaceTable  = null;
 
            if (_propertiesCollection != null)
            {
                _propertiesCollection.Clear();
            }
 
            base.Clear();
        }
 
        #endregion Public Methods
 
        #region Private Data
 
        private
        object                               _targetObject;
        private
        MetroSerializationNamespaceTable     _namespaceTable;
        private
        SerializablePropertyCollection       _propertiesCollection;
        private
        bool                                 _isComplexValue;
        private
        bool                                 _isReadOnlyValue;
        private
        SerializablePropertyContext          _backingPropertyContext;
        static
        Stack                                _recycableSerializableObjectContexts;
        static
        object                               _stackLock = new Object();
 
        #endregion Private Data
    };
}