protected virtual void SerializeClone(object obj, ReadOnlyClone clone, string id, string key)
        {
            IObjectManager   om       = this.Context.ObjectManager;
            IDomainMap       dm       = this.Context.DomainMap;
            IAssemblyManager am       = this.Context.AssemblyManager;
            IClassMap        classMap = dm.MustGetClassMap(obj.GetType());
            IListManager     lm       = this.Context.ListManager;

            clone.Identity = id;
            clone.Key      = key;
            clone.Type     = classMap.GetFullName();
            foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps())
            {
                if (propertyMap.ReferenceType == ReferenceType.None)
                {
                    if (propertyMap.IsCollection)
                    {
                        IList values = new ArrayList();
                        IList list   = (IList)om.GetPropertyValue(obj, propertyMap.Name);

                        foreach (object value in list)
                        {
                            values.Add(value);
                        }

                        clone.PropertyValues[propertyMap.Name]    = values;
                        clone.NullValueStatuses[propertyMap.Name] = false;
                    }
                    else
                    {
                        object value = om.GetPropertyValue(obj, propertyMap.Name);
                        clone.PropertyValues[propertyMap.Name]    = value;
                        clone.NullValueStatuses[propertyMap.Name] = om.GetNullValueStatus(obj, propertyMap.Name);
                    }
                }
                else
                {
                    IClassMap refClassMap = propertyMap.MustGetReferencedClassMap();
                    if (refClassMap.IsReadOnly)
                    {
                        if (propertyMap.IsCollection)
                        {
                            IList values = new ArrayList();
                            IList list   = (IList)om.GetPropertyValue(obj, propertyMap.Name);

                            foreach (object value in list)
                            {
                                if (value != null)
                                {
                                    refClassMap = dm.MustGetClassMap(value.GetType());
                                    string refIdentity        = om.GetObjectIdentity(value);
                                    SerializedReference refId = new SerializedReference(refIdentity, refClassMap.GetFullName());
                                    values.Add(refId);
                                }
                            }
                            clone.PropertyValues[propertyMap.Name]    = values;
                            clone.NullValueStatuses[propertyMap.Name] = false;
                        }
                        else
                        {
                            object value = om.GetPropertyValue(obj, propertyMap.Name);
                            if (value != null)
                            {
                                refClassMap = dm.MustGetClassMap(value.GetType());
                                string refIdentity        = om.GetObjectIdentity(value);
                                SerializedReference refId = new SerializedReference(refIdentity, refClassMap.GetFullName());
                                value = refId;
                            }
                            clone.PropertyValues[propertyMap.Name]    = value;
                            clone.NullValueStatuses[propertyMap.Name] = om.GetNullValueStatus(obj, propertyMap.Name);
                        }
                    }
                }
            }
        }
        protected virtual void DeserializeClone(object obj, ReadOnlyClone clone)
        {
            IObjectManager   om       = this.Context.ObjectManager;
            IDomainMap       dm       = this.Context.DomainMap;
            IAssemblyManager am       = this.Context.AssemblyManager;
            IClassMap        classMap = dm.MustGetClassMap(obj.GetType());
            IListManager     lm       = this.Context.ListManager;

            foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps())
            {
                if (propertyMap.ReferenceType == ReferenceType.None)
                {
                    if (propertyMap.IsCollection)
                    {
                        IList values = (IList)clone.PropertyValues[propertyMap.Name];
                        IList list   = (IList)om.GetPropertyValue(obj, propertyMap.Name);

                        bool stackMute           = false;
                        IInterceptableList mList = list as IInterceptableList;
                        if (mList != null)
                        {
                            stackMute        = mList.MuteNotify;
                            mList.MuteNotify = true;
                        }
                        list.Clear();

                        foreach (object value in values)
                        {
                            list.Add(value);
                        }

                        IList cloneList = new ArrayList(list);

                        if (mList != null)
                        {
                            mList.MuteNotify = stackMute;
                        }

                        om.SetOriginalPropertyValue(obj, propertyMap.Name, cloneList);
                        om.SetNullValueStatus(obj, propertyMap.Name, false);
                    }
                    else
                    {
                        object value = clone.PropertyValues[propertyMap.Name];
                        om.SetPropertyValue(obj, propertyMap.Name, value);
                        om.SetOriginalPropertyValue(obj, propertyMap.Name, value);
                        om.SetNullValueStatus(obj, propertyMap.Name, (bool)clone.NullValueStatuses[propertyMap.Name]);
                    }
                }
                else
                {
                    IClassMap refClassMap = propertyMap.MustGetReferencedClassMap();
                    if (refClassMap.IsReadOnly)
                    {
                        if (propertyMap.IsCollection)
                        {
                            IList values = (IList)clone.PropertyValues[propertyMap.Name];
                            IList list   = (IList)om.GetPropertyValue(obj, propertyMap.Name);

                            bool stackMute           = false;
                            IInterceptableList mList = list as IInterceptableList;
                            if (mList != null)
                            {
                                stackMute        = mList.MuteNotify;
                                mList.MuteNotify = true;
                            }
                            list.Clear();

                            foreach (SerializedReference refId in values)
                            {
                                object value = null;
                                if (refId != null)
                                {
                                    refClassMap = dm.MustGetClassMap(refId.Type);
                                    Type refType = am.GetTypeFromClassMap(refClassMap);
                                    value = this.Context.GetObjectById(refId.Identity, refType, true);
                                    list.Add(value);
                                }
                            }

                            IList cloneList = new ArrayList(list);

                            if (mList != null)
                            {
                                mList.MuteNotify = stackMute;
                            }

                            om.SetOriginalPropertyValue(obj, propertyMap.Name, cloneList);
                            om.SetNullValueStatus(obj, propertyMap.Name, false);
                        }
                        else
                        {
                            object value = null;
                            SerializedReference refId = (SerializedReference)clone.PropertyValues[propertyMap.Name];
                            if (refId != null)
                            {
                                refClassMap = dm.MustGetClassMap(refId.Type);
                                Type refType = am.GetTypeFromClassMap(refClassMap);
                                value = this.Context.GetObjectById(refId.Identity, refType, true);
                            }
                            om.SetPropertyValue(obj, propertyMap.Name, value);
                            om.SetOriginalPropertyValue(obj, propertyMap.Name, value);
                            om.SetNullValueStatus(obj, propertyMap.Name, (bool)clone.NullValueStatuses[propertyMap.Name]);
                        }
                    }
                }
            }
        }
        protected virtual void SerializeClone(object obj, ReadOnlyClone clone, string id, string key)
        {
            IObjectManager om = this.Context.ObjectManager ;
            IDomainMap dm = this.Context.DomainMap;
            IAssemblyManager am = this.Context.AssemblyManager;
            IClassMap classMap = dm.MustGetClassMap(obj.GetType() );
            IListManager lm = this.Context.ListManager ;
            clone.Identity = id;
            clone.Key = key;
            clone.Type = classMap.GetFullName();
            foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps() )
            {
                if (propertyMap.ReferenceType == ReferenceType.None)
                {
                    if (propertyMap.IsCollection)
                    {
                        IList values = new ArrayList()  ;
                        IList list = (IList) om.GetPropertyValue(obj, propertyMap.Name);

                        foreach (object value in list)
                            values.Add(value);

                        clone.PropertyValues[propertyMap.Name] = values;
                        clone.NullValueStatuses[propertyMap.Name] = false;
                    }
                    else
                    {
                        object value = om.GetPropertyValue(obj, propertyMap.Name);
                        clone.PropertyValues[propertyMap.Name] = value;
                        clone.NullValueStatuses[propertyMap.Name] = om.GetNullValueStatus(obj, propertyMap.Name);
                    }
                }
                else
                {
                    IClassMap refClassMap = propertyMap.MustGetReferencedClassMap() ;
                    if (refClassMap.IsReadOnly)
                    {
                        if (propertyMap.IsCollection)
                        {
                            IList values = new ArrayList() ;
                            IList list = (IList) om.GetPropertyValue(obj, propertyMap.Name);

                            foreach (object value in list)
                            {
                                if (value != null)
                                {
                                    refClassMap = dm.MustGetClassMap(value.GetType() );
                                    string refIdentity = om.GetObjectIdentity(value);
                                    SerializedReference refId = new SerializedReference(refIdentity, refClassMap.GetFullName()) ;
                                    values.Add(refId);
                                }
                            }
                            clone.PropertyValues[propertyMap.Name] = values;
                            clone.NullValueStatuses[propertyMap.Name] = false;
                        }
                        else
                        {
                            object value = om.GetPropertyValue(obj, propertyMap.Name) ;
                            if (value != null)
                            {
                                refClassMap = dm.MustGetClassMap(value.GetType() );
                                string refIdentity = om.GetObjectIdentity(value);
                                SerializedReference refId = new SerializedReference(refIdentity, refClassMap.GetFullName()) ;
                                value = refId;
                            }
                            clone.PropertyValues[propertyMap.Name] = value;
                            clone.NullValueStatuses[propertyMap.Name] = om.GetNullValueStatus(obj, propertyMap.Name);
                        }
                    }
                }
            }
        }