/// <summary>
        /// Throws an exception if the media object should not be added
        /// as a child.
        /// </summary>
        /// <param name="media"></param>
        /// <returns></returns>
        /// <exception cref="InvalidCastException">
        /// Thrown if the "media" argument is not an <see cref="IDvItem"/> or an <see cref="IDvContainer"/> object.
        /// Also thrown if the underlying referenced item of "media" is not an <see cref="IDvItem"/>.
        /// </exception>
        /// <exception cref="Error_PendingDeleteException">
        /// Thrown if the underlying referenced item of "media" is slated for deletion.
        /// </exception>
        private void ThrowExceptionIfBad(IDvMedia media)
        {
            if (media.IsItem)
            {
                // perform an explicit cast - throws InvalidCastException if error
                IDvItem dvItem = (IDvItem)media;

                if (media.IsReference)
                {
                    IDvItem underlying = dvItem.RefItem as IDvItem;
                    if (underlying == null)
                    {
                        throw new InvalidCastException("Cannot convert media.RefItem to IDvItem");
                    }
                    else if (underlying.IsDeletePending)
                    {
                        throw new Error_PendingDeleteException(underlying);
                    }
                }
            }
            else
            {
                // perform an explicit cast - throws InvalidCastException if error
                IDvContainer dvContainer = (IDvContainer)media;
            }
        }
        /// <summary>
        /// <see cref="DvMediaContainer.RemoveObject"/>
        /// and <see cref="DvMediaContainer.RemoveObjects"/>
        /// call this method before removing it from its child list.
        /// This will automatically remove items that refer to this item
        /// from their respective parents.
        /// </summary>
        public void NotifyPendingDelete()
        {
            lock (this.m_LockReferences)
            {
                this.m_Deleting = true;

                ArrayList removeThese = new ArrayList();

                if (m_ReferringItems != null)
                {
                    //foreach (WeakReference wr in this.m_ReferringItems)
                    foreach (IDvItem referringItem in this.m_ReferringItems)
                    {
                        // force a strong reference of the target before checking it's alive

                        //IDvItem referringItem = (IDvItem) wr.Target;
                        //if (wr.IsAlive)
                        //{
                        IDvContainer parent = (IDvContainer)referringItem.Parent;

                        if (parent != null)
                        {
                            parent.RemoveObject(referringItem);
                        }
                        else
                        {
                            //removeThese.Add(wr);
                            removeThese.Add(referringItem);
                        }
                        //}
                        //else
                        //{
                        //	removeThese.Add(wr);
                        //}
                    }

                    //foreach (WeakReference wr in removeThese)
                    foreach (IDvItem referringItem in removeThese)
                    {
                        //this.m_ReferringItems.Remove(wr);
                        this.m_ReferringItems.Remove(referringItem);
                    }
                }

                this.m_ReferringItems = null;
                this.m_RefItem        = null;
            }
        }
        /// <summary>
        /// If this container changes, this method should be called
        /// so that the root container of the hierarchy knows that
        /// the state of the hierarchy has changed.
        /// </summary>
        public virtual void NotifyRootOfChange()
        {
            this.m_UpdateID++;
            IDvContainer c = this;

            while (c.Parent != null)
            {
                c = (IDvContainer)c.Parent;
            }

            if (c.GetType() == TYPE_DV_ROOT)
            {
                DvRootContainer root = (DvRootContainer)c;
                root.FireOnContainerChanged(this);
            }
        }
        /// <summary>
        /// This removes a container or item object from
        /// the child list. It is used by other
        /// RemoveXXX methods defined in this class
        /// and implements the portion that allows
        /// proper media server eventing.
        /// <para>
        /// Method properly tells items to notify all other
        /// items that reference it that it will be deleted.
        /// </para>
        /// <para>
        /// Method properly tells containers to recursively
        /// remove their child objects, so that descendent
        /// reference items are properly removed.
        /// </para>
        /// </summary>
        /// <param name="removeThis"></param>
        public override void RemoveObject(IUPnPMedia removeThis)
        {
            IDvMedia     dv        = removeThis as IDvMedia;
            IDvItem      item      = removeThis as IDvItem;
            IDvContainer container = removeThis as IDvContainer;

            // Before we go about doing any removal operations,
            // we fire the event to indicate this object is
            // about to be removed.
            ArrayList removeThese = new ArrayList(1);

            removeThese.Add(removeThis);
            if (this.OnChildrenToRemove != null)
            {
                this.OnChildrenToRemove(this, removeThese);
            }

            if (item != null)
            {
                // Notify any and all referring items that
                // this object is about to be removed
                // from its parent.
                item.NotifyPendingDelete();
            }
            else if (container != null)
            {
                // Instruct all child containers to
                // remove their own children.
                IList children = container.CompleteList;
                foreach (IDvMedia child in children)
                {
                    container.RemoveObject(child);
                }
            }

            // go ahead and remove this object
            base.RemoveObject(removeThis);

            // Notify that the child has formerly been
            // removed.
            if (this.OnChildrenRemoved != null)
            {
                this.OnChildrenRemoved(this, removeThese);
            }

            this.NotifyRootOfChange();
        }
 /// <summary>
 /// This removes a container and all of its descendents.
 /// Any items that reference a deleted descendent will
 /// be notified to delete themselves from their parent containers.
 /// Local binaries associated as resources are not deleted.
 /// Control points must call DeleteResource first.
 /// </summary>
 /// <param name="removeThis">the container to remove</param>
 private void RemoveContainer(IDvContainer removeThis)
 {
     this.RemoveObject(removeThis);
 }
 /// <summary>
 /// <para>
 /// Adds a child container to this container.
 /// </para>
 ///
 /// <para>
 /// Method was formerly public - now private.
 /// </para>
 /// </summary>
 /// <param name="addThis">the new child container to add, instantiated from
 /// <see cref="DvMediaBuilder.CreateContainer"/>.
 /// </param>
 private void AddContainer(IDvContainer addThis)
 {
     this.AddObject(addThis, false);
 }
 /// <summary>
 /// Changes this object's parent to another container.
 /// Strongly recommended that this container already
 /// share the object's current hierarchy.
 /// </summary>
 /// <param name="diffParent"></param>
 /// <exception cref="InvalidCastException">
 /// Thrown if this object was improperly added to a
 /// container that is not a <see cref="DvMediaContainer"/>.
 /// </exception>
 public void ChangeParent(IDvContainer diffParent)
 {
     DvMediaContainer.ChangeParent2(this, (DvMediaContainer)diffParent);
 }
 private void Sink_OnChildRemoved(IDvContainer parent, ICollection removedThese)
 {
     foreach (IUPnPMedia removed in removedThese)
     {
         DvMediaContainer mc = removed as DvMediaContainer;
         if (mc != null)
         {
             mc.OnChildrenRemoved -= new DvDelegates.Delegate_OnChildrenRemove(this.Sink_OnChildRemoved);;
             mc.Callback_UpdateMetadata = null;
         }
     }
 }
 /// <summary>
 /// Changes this object's parent to another container.
 /// Strongly recommended that this container already
 /// share the object's current hierarchy.
 /// </summary>
 /// <param name="diffParent"></param>
 /// <exception cref="InvalidCastException">
 /// Thrown if this object was improperly added to a 
 /// container that is not a <see cref="DvMediaContainer"/>.
 /// </exception>
 public void ChangeParent(IDvContainer diffParent)
 {
     DvMediaContainer.ChangeParent2(this, (DvMediaContainer)diffParent);
 }
 /// <summary>
 /// Not implemented.
 /// </summary>
 /// <param name="ignored"></param>
 public void ChangeParent(IDvContainer ignored)
 {
 }
 /// <summary>
 /// This removes a container and all of its descendents.
 /// Any items that reference a deleted descendent will
 /// be notified to delete themselves from their parent containers.
 /// Local binaries associated as resources are not deleted.
 /// Control points must call DeleteResource first.
 /// </summary>
 /// <param name="removeThis">the container to remove</param>
 private void RemoveContainer(IDvContainer removeThis)
 {
     this.RemoveObject(removeThis);
 }
 /// <summary>
 /// <para>
 /// Adds a child container to this container.
 /// </para>
 /// 
 /// <para>
 /// Method was formerly public - now private.
 /// </para>
 /// </summary>
 /// <param name="addThis">the new child container to add, instantiated from 
 /// <see cref="DvMediaBuilder.CreateContainer"/>.
 /// </param>
 private void AddContainer(IDvContainer addThis)
 {
     this.AddObject(addThis, false);
 }