System.ComponentModel.TypeDescriptor.NodeRemove C# (CSharp) Method

NodeRemove() private static method

Simple linked list code to remove an element from the list. Returns the new head to the list. If the head points to an instance of DelegatingTypeDescriptionProvider, we clear the node because all it is doing is delegating elsewhere. Note that this behaves a little differently from normal linked list code. In a normal linked list, you remove then target node and fixup the links. In this linked list, we remove the node AFTER the target node, fixup the links, and fixup the underlying providers that each node references. The reason for this is that most providers keep a reference to the previous provider, which is exposed as one of these nodes. Therefore, to remove a provider the node following is most likely referenced by that provider
private static NodeRemove ( object key, TypeDescriptionProvider provider ) : void
key object
provider TypeDescriptionProvider
return void
        private static void NodeRemove(object key, TypeDescriptionProvider provider)
        {
            lock (s_providerTable)
            {
                TypeDescriptionNode head = (TypeDescriptionNode)s_providerTable[key];
                TypeDescriptionNode target = head;
                TypeDescriptionNode prev = null;

                while (target != null && target.Provider != provider)
                {
                    prev = target;
                    target = target.Next;
                }

                if (target != null)
                {
                    // We have our target node.  There are three cases
                    // to consider:  the target is in the middle, the head,
                    // or the end.

                    if (target.Next != null)
                    {
                        // If there is a node after the target node,
                        // steal the node's provider and store it
                        // at the target location.  This removes
                        // the provider at the target location without
                        // the need to modify providers which may be
                        // pointing to "target".  
                        target.Provider = target.Next.Provider;

                        // Now remove target.Next from the list
                        target.Next = target.Next.Next;

                        // If the new provider we got is a delegating
                        // provider, we can remove this node from 
                        // the list.  The delegating provider should
                        // always be at the end of the node list.
                        if (target == head && target.Provider is DelegatingTypeDescriptionProvider)
                        {
                            Debug.Assert(target.Next == null, "Delegating provider should always be the last provider in the chain.");
                            s_providerTable.Remove(key);
                        }
                    }
                    else if (target != head)
                    {
                        // If target is the last node, we can't
                        // assign a new provider over to it.  What
                        // we can do, however, is assign a delegating
                        // provider into the target node.  This routes
                        // requests from the previous provider into
                        // the next base type provider list.

                        // We don't do this if the target is the head.
                        // In that case, we can remove the node
                        // altogether since no one is pointing to it.

                        Type keyType = key as Type;
                        if (keyType == null) keyType = key.GetType();

                        target.Provider = new DelegatingTypeDescriptionProvider(keyType.GetTypeInfo().BaseType);
                    }
                    else
                    {
                        s_providerTable.Remove(key);
                    }

                    // Finally, clear our cache of provider types; it might be invalid 
                    // now.
                    s_providerTypeTable.Clear();
                }
            }
        }