The Labs \ Source Viewer \ SSCLI \ System.ComponentModel \ MergedTypeDescriptor

  1. //------------------------------------------------------------------------------
  2. // <copyright file="TypeDescriptor.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. /*
  16. */
  17. namespace System.ComponentModel
  18. {
  19.     using System.Runtime.Serialization.Formatters;
  20.     using System.Threading;
  21.     using System.Runtime.Remoting.Activation;
  22.     using System.Runtime.InteropServices;
  23.     using System.Diagnostics;
  24.     using System;
  25.     using CodeAccessPermission = System.Security.CodeAccessPermission;
  26.     using System.Security.Permissions;
  27.     using System.Collections;
  28.     using System.Globalization;
  29.     using System.IO;
  30.     using System.Reflection;
  31.     using Microsoft.Win32;
  32.     using System.ComponentModel.Design;
  33.     using System.Diagnostics.CodeAnalysis;
  34.     using System.Runtime.Versioning;
  35.    
  36.     /// <devdoc>
  37.     /// Provides information about the properties and events
  38.     /// for a component. This class cannot be inherited.
  39.     /// </devdoc>
  40.     [HostProtection(SharedState = true)]
  41.     public sealed class TypeDescriptor
  42.     {
  43.         // Note: this is initialized at class load because we
  44.         // lock on it for thread safety. It is used from nearly
  45.         // every call to this class, so it will be created soon after
  46.         // class load anyway.
  47.         private static WeakHashtable _providerTable = new WeakHashtable();
  48.         // mapping of type or object hash to a provider list
  49.         private static Hashtable _providerTypeTable = new Hashtable();
  50.         // A direct mapping from type to provider.
  51.         private static Hashtable _defaultProviders = new Hashtable();
  52.         // A table of type -> default provider to track DefaultTypeDescriptionProviderAttributes.
  53.         private static WeakHashtable _associationTable;
  54.         private static int _metadataVersion;
  55.         // a version stamp for our metadata. Used by property descriptors to know when to rebuild
  56.         // attributes.
  57.        
  58.         // This is an index that we use to create a unique name for a property in the
  59.         // event of a name collision. The only time we should use this is when
  60.         // a name collision happened on an extender property that has no site or
  61.         // no name on its site. Should be very rare.
  62.         private static int _collisionIndex;
  63.        
  64.         // events
  65.         private static RefreshEventHandler _refreshHandler;
  66.        
  67.         private static BooleanSwitch TraceDescriptor = new BooleanSwitch("TypeDescriptor", "Debug TypeDescriptor.");
  68.        
  69.         #if DEBUG
  70.         private static BooleanSwitch EnableValidation = new BooleanSwitch("EnableValidation", "Enable type descriptor Whidbey->RTM validation");
  71.         #endif
  72.        
  73.         // For each stage of our filtering pipeline, the pipeline needs to know
  74.         // what it is filtering.
  75.         private const int PIPELINE_ATTRIBUTES = 0;
  76.         private const int PIPELINE_PROPERTIES = 1;
  77.         private const int PIPELINE_EVENTS = 2;
  78.        
  79.         // And each stage of the pipeline needs to have its own
  80.         // keys for its cache table. We use guids because they
  81.         // are unique and fast to compare. The order for each of
  82.         // these keys must match the Id's of the filter type above.
  83.             // attributes
  84.             // properties
  85.             // events
  86.         private static readonly Guid[] _pipelineInitializeKeys = new Guid[] {Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()};
  87.        
  88.             // attributes
  89.             // properties
  90.             // events
  91.         private static readonly Guid[] _pipelineMergeKeys = new Guid[] {Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()};
  92.        
  93.             // attributes
  94.             // properties
  95.             // events
  96.         private static readonly Guid[] _pipelineFilterKeys = new Guid[] {Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()};
  97.        
  98.             // attributes
  99.             // properties
  100.             // events
  101.         private static readonly Guid[] _pipelineAttributeFilterKeys = new Guid[] {Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()};
  102.        
  103.         private static object _internalSyncObject = new object();
  104.        
  105.         private TypeDescriptor()
  106.         {
  107.         }
  108.        
  109.         /// <internalonly/>
  110.         /// <devdoc>
  111.         /// </devdoc>
  112.         [Obsolete("This property has been deprecated. Use a type description provider to supply type information for COM types instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  113.         public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
  114.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  115.             get {
  116.                 TypeDescriptionNode node = NodeFor(ComObjectType);
  117.                 ComNativeDescriptionProvider provider = null;
  118.                
  119.                 do {
  120.                     provider = node.Provider as ComNativeDescriptionProvider;
  121.                     node = node.Next;
  122.                 }
  123.                 while (node != null && provider == null);
  124.                
  125.                 if (provider != null) {
  126.                     return provider.Handler;
  127.                 }
  128.                
  129.                 return null;
  130.             }
  131.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  132.             set {
  133.                 TypeDescriptionNode node = NodeFor(ComObjectType);
  134.                
  135.                 while (node != null && !(node.Provider is ComNativeDescriptionProvider)) {
  136.                     node = node.Next;
  137.                 }
  138.                
  139.                 if (node == null) {
  140.                     AddProvider(new ComNativeDescriptionProvider(value), ComObjectType);
  141.                 }
  142.                 else {
  143.                     ComNativeDescriptionProvider provider = (ComNativeDescriptionProvider)node.Provider;
  144.                     provider.Handler = value;
  145.                 }
  146.             }
  147.         }
  148.        
  149.        
  150.         /// <devdoc>
  151.         /// This property returns a Type object that can be passed to the various
  152.         /// AddProvider methods to define a type description provider for COM types.
  153.         /// </devdoc>
  154.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  155.         public static Type ComObjectType {
  156.             get { return typeof(TypeDescriptorComObject); }
  157.         }
  158.        
  159.         /// <devdoc>
  160.         /// This value increments each time someone refreshes or changes metadata.
  161.         /// </devdoc>
  162.         static internal int MetadataVersion {
  163.             get { return _metadataVersion; }
  164.         }
  165.        
  166.         /// <include file='doc\TypeDescriptor.uex' path='docs/doc[@for="TypeDescriptor.Refreshed"]/*' />
  167.         /// <devdoc>
  168.         /// Occurs when Refreshed is raised for a component.
  169.         /// </devdoc>
  170.         public static event RefreshEventHandler Refreshed {
  171.             add { _refreshHandler += value; }
  172.             remove { _refreshHandler -= value; }
  173.         }
  174.        
  175.         /// <devdoc>
  176.         /// The AddAttributes method allows you to add class-level attributes for a
  177.         /// type or an instance. This method simply implements a type description provider
  178.         /// that merges the provided attributes with the attributes that already exist on
  179.         /// the class. This is a short cut for such a behavior. Adding additional
  180.         /// attributes is common need for applications using the Windows Forms property
  181.         /// window. The return value form AddAttributes is the TypeDescriptionProvider
  182.         /// that was used to add the attributes. This provider can later be passed to
  183.         /// RemoveProvider if the added attributes are no longer needed.
  184.         /// </devdoc>
  185.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  186.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  187.         public static TypeDescriptionProvider AddAttributes(Type type, params Attribute[] attributes)
  188.         {
  189.            
  190.             if (type == null) {
  191.                 throw new ArgumentNullException("type");
  192.             }
  193.            
  194.             if (attributes == null) {
  195.                 throw new ArgumentNullException("attributes");
  196.             }
  197.            
  198.             TypeDescriptionProvider existingProvider = GetProvider(type);
  199.             TypeDescriptionProvider provider = new AttributeProvider(existingProvider, attributes);
  200.             TypeDescriptor.AddProvider(provider, type);
  201.             return provider;
  202.         }
  203.        
  204.         /// <devdoc>
  205.         /// The AddAttributes method allows you to add class-level attributes for a
  206.         /// type or an instance. This method simply implements a type description provider
  207.         /// that merges the provided attributes with the attributes that already exist on
  208.         /// the class. This is a short cut for such a behavior. Adding additional
  209.         /// attributes is common need for applications using the Windows Forms property
  210.         /// window. The return value form AddAttributes is the TypeDescriptionProvider
  211.         /// that was used to add the attributes. This provider can later be passed to
  212.         /// RemoveProvider if the added attributes are no longer needed.
  213.         /// </devdoc>
  214.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  215.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  216.         public static TypeDescriptionProvider AddAttributes(object instance, params Attribute[] attributes)
  217.         {
  218.            
  219.             if (instance == null) {
  220.                 throw new ArgumentNullException("instance");
  221.             }
  222.            
  223.             if (attributes == null) {
  224.                 throw new ArgumentNullException("attributes");
  225.             }
  226.            
  227.             TypeDescriptionProvider existingProvider = GetProvider(instance);
  228.             TypeDescriptionProvider provider = new AttributeProvider(existingProvider, attributes);
  229.             TypeDescriptor.AddProvider(provider, instance);
  230.             return provider;
  231.         }
  232.        
  233.         /// <internalonly/>
  234.         /// <devdoc>
  235.         /// Adds an editor table for the given editor base type.
  236.         /// ypically, editors are specified as metadata on an object. If no metadata for a
  237.         /// equested editor base type can be found on an object, however, the
  238.         /// ypeDescriptor will search an editor
  239.         /// able for the editor type, if one can be found.
  240.         /// </devdoc>
  241.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  242.         public static void AddEditorTable(Type editorBaseType, Hashtable table)
  243.         {
  244.             ReflectTypeDescriptionProvider.AddEditorTable(editorBaseType, table);
  245.         }
  246.        
  247.         /// <devdoc>
  248.         /// Adds a type description provider that will be called on to provide
  249.         /// type and instance information for any object that is of, or a subtype
  250.         /// of, the provided type. Type can be any type, including interfaces.
  251.         /// For example, to provide custom type and instance information for all
  252.         /// components, you would pass typeof(IComponent). Passing typeof(object)
  253.         /// will cause the provider to be called to provide type information for
  254.         /// all types.
  255.         /// </devdoc>
  256.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  257.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  258.         public static void AddProvider(TypeDescriptionProvider provider, Type type)
  259.         {
  260.             if (provider == null) {
  261.                 throw new ArgumentNullException("provider");
  262.             }
  263.            
  264.             if (type == null) {
  265.                 throw new ArgumentNullException("type");
  266.             }
  267.            
  268.             lock (_providerTable) {
  269.                 // Get the root node, hook it up, and stuff it back into
  270.                 // the provider cache.
  271.                 TypeDescriptionNode node = NodeFor(type, true);
  272.                 TypeDescriptionNode head = new TypeDescriptionNode(provider);
  273.                 head.Next = node;
  274.                 _providerTable[type] = head;
  275.                 _providerTypeTable.Clear();
  276.             }
  277.            
  278.             Refresh(type);
  279.         }
  280.        
  281.         /// <devdoc>
  282.         /// Adds a type description provider that will be called on to provide
  283.         /// type information for a single object instance. A provider added
  284.         /// using this method will never have its CreateInstance method called
  285.         /// because the instance already exists. This method does not prevent
  286.         /// the object from finalizing.
  287.         /// </devdoc>
  288.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  289.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  290.         public static void AddProvider(TypeDescriptionProvider provider, object instance)
  291.         {
  292.             if (provider == null) {
  293.                 throw new ArgumentNullException("provider");
  294.             }
  295.            
  296.             if (instance == null) {
  297.                 throw new ArgumentNullException("instance");
  298.             }
  299.            
  300.             // Get the root node, hook it up, and stuff it back into
  301.             // the provider cache.
  302.             lock (_providerTable) {
  303.                 TypeDescriptionNode node = NodeFor(instance, true);
  304.                 TypeDescriptionNode head = new TypeDescriptionNode(provider);
  305.                 head.Next = node;
  306.                 _providerTable.SetWeak(instance, head);
  307.                 _providerTypeTable.Clear();
  308.             }
  309.            
  310.             Refresh(instance);
  311.         }
  312.        
  313.         /// <devdoc>
  314.         /// This method verifies that we have checked for the presence
  315.         /// of a default type description provider attribute for the
  316.         /// given type.
  317.         /// </devdoc>
  318.         //See security note below
  319.         [SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts")]
  320.         private static void CheckDefaultProvider(Type type)
  321.         {
  322.             if (_defaultProviders == null) {
  323.                 lock (_internalSyncObject) {
  324.                     if (_defaultProviders == null) {
  325.                         _defaultProviders = new Hashtable();
  326.                     }
  327.                 }
  328.             }
  329.            
  330.             if (_defaultProviders.ContainsKey(type)) {
  331.                 return;
  332.             }
  333.            
  334.             // Immediately clear this. If we find a default provider
  335.             // and it starts messing around with type information,
  336.             // this could infinitely recurse.
  337.             //
  338.             _defaultProviders[type] = null;
  339.            
  340.             // Always use core reflection when checking for
  341.             // the default provider attribute. If there is a
  342.             // provider, we probably don't want to build up our
  343.             // own cache state against the type. There shouldn't be
  344.             // more than one of these, but walk anyway. Walk in
  345.             // reverse order so that the most derived takes precidence.
  346.             //
  347.             object[] attrs = type.GetCustomAttributes(typeof(TypeDescriptionProviderAttribute), false);
  348.             bool providerAdded = false;
  349.             for (int idx = attrs.Length - 1; idx >= 0; idx--) {
  350.                 TypeDescriptionProviderAttribute pa = (TypeDescriptionProviderAttribute)attrs[idx];
  351.                 Type providerType = Type.GetType(pa.TypeName);
  352.                 if (providerType != null && typeof(TypeDescriptionProvider).IsAssignableFrom(providerType)) {
  353.                     TypeDescriptionProvider prov;
  354.                    
  355.                     IntSecurity.FullReflection.Assert();
  356.                     try {
  357.                         prov = (TypeDescriptionProvider)Activator.CreateInstance(providerType);
  358.                     }
  359.                     finally {
  360.                         CodeAccessPermission.RevertAssert();
  361.                     }
  362.                     Trace("Providers : Default provider found : {0}", providerType.Name);
  363.                     AddProvider(prov, type);
  364.                     providerAdded = true;
  365.                 }
  366.             }
  367.            
  368.             // If we did not add a provider, check the base class.
  369.             if (!providerAdded) {
  370.                 Type baseType = type.BaseType;
  371.                 if (baseType != null && baseType != type) {
  372.                     CheckDefaultProvider(baseType);
  373.                 }
  374.             }
  375.         }
  376.        
  377.         /// <devdoc>
  378.         /// The CreateAssocation method creates an association between two objects.
  379.         /// Once an association is created, a designer or other filtering mechanism
  380.         /// can add properties that route to either object into the primary object's
  381.         /// property set. When a property invocation is made against the primary
  382.         /// object, GetAssocation will be called to resolve the actual object
  383.         /// instance that is related to its type parameter.
  384.         /// </devdoc>
  385.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  386.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  387.         public static void CreateAssociation(object primary, object secondary)
  388.         {
  389.             if (primary == null) {
  390.                 throw new ArgumentNullException("primary");
  391.             }
  392.            
  393.             if (secondary == null) {
  394.                 throw new ArgumentNullException("secondary");
  395.             }
  396.            
  397.             if (primary == secondary) {
  398.                 throw new ArgumentException(SR.GetString(SR.TypeDescriptorSameAssociation));
  399.             }
  400.            
  401.             if (_associationTable == null) {
  402.                 lock (_internalSyncObject) {
  403.                     if (_associationTable == null) {
  404.                         _associationTable = new WeakHashtable();
  405.                     }
  406.                 }
  407.             }
  408.            
  409.             IList associations = (IList)_associationTable[primary];
  410.            
  411.             if (associations == null) {
  412.                 lock (_associationTable) {
  413.                     associations = (IList)_associationTable[primary];
  414.                     if (associations == null) {
  415.                         associations = new ArrayList(4);
  416.                         _associationTable.SetWeak(primary, associations);
  417.                     }
  418.                 }
  419.             }
  420.             else {
  421.                 for (int idx = associations.Count - 1; idx >= 0; idx--) {
  422.                     WeakReference r = (WeakReference)associations[idx];
  423.                     if (r.IsAlive && r.Target == secondary) {
  424.                         throw new ArgumentException(SR.GetString(SR.TypeDescriptorAlreadyAssociated));
  425.                     }
  426.                 }
  427.             }
  428.            
  429.             lock (associations) {
  430.                 associations.Add(new WeakReference(secondary));
  431.             }
  432.         }
  433.        
  434.         /// <devdoc>
  435.         /// Creates an instance of the designer associated with the
  436.         /// specified component.
  437.         /// </devdoc>
  438.         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2113:SecureLateBindingMethods")]
  439.         public static IDesigner CreateDesigner(IComponent component, Type designerBaseType)
  440.         {
  441.             Type designerType = null;
  442.             IDesigner designer = null;
  443.            
  444.             // Get the set of attributes for this type
  445.             //
  446.             AttributeCollection attributes = GetAttributes(component);
  447.            
  448.             for (int i = 0; i < attributes.Count; i++) {
  449.                 DesignerAttribute da = attributes[i] as DesignerAttribute;
  450.                 if (da != null) {
  451.                     Type attributeBaseType = Type.GetType(da.DesignerBaseTypeName);
  452.                     if (attributeBaseType != null && attributeBaseType == designerBaseType) {
  453.                         ISite site = component.Site;
  454.                         bool foundService = false;
  455.                        
  456.                         if (site != null) {
  457.                             ITypeResolutionService tr = (ITypeResolutionService)site.GetService(typeof(ITypeResolutionService));
  458.                             if (tr != null) {
  459.                                 foundService = true;
  460.                                 designerType = tr.GetType(da.DesignerTypeName);
  461.                             }
  462.                         }
  463.                        
  464.                         if (!foundService) {
  465.                             designerType = Type.GetType(da.DesignerTypeName);
  466.                         }
  467.                        
  468.                         Debug.Assert(designerType != null, "It may be okay for the designer not to load, but we failed to load designer for component of type '" + component.GetType().FullName + "' because designer of type '" + da.DesignerTypeName + "'");
  469.                         if (designerType != null) {
  470.                             break;
  471.                         }
  472.                     }
  473.                 }
  474.             }
  475.            
  476.             if (designerType != null) {
  477.                 designer = (IDesigner)SecurityUtils.SecureCreateInstance(designerType, null, true);
  478.             }
  479.            
  480.             return designer;
  481.         }
  482.        
  483.         /// <devdoc>
  484.         /// This dynamically binds an EventDescriptor to a type.
  485.         /// </devdoc>
  486.         [ReflectionPermission(SecurityAction.LinkDemand, Flags = ReflectionPermissionFlag.MemberAccess)]
  487.         public static EventDescriptor CreateEvent(Type componentType, string name, Type type, params Attribute[] attributes)
  488.         {
  489.             return new ReflectEventDescriptor(componentType, name, type, attributes);
  490.         }
  491.        
  492.         /// <devdoc>
  493.         /// This creates a new event descriptor identical to an existing event descriptor. The new event descriptor
  494.         /// has the specified metadata attributes merged with the existing metadata attributes.
  495.         /// </devdoc>
  496.         [ReflectionPermission(SecurityAction.LinkDemand, Flags = ReflectionPermissionFlag.MemberAccess)]
  497.         public static EventDescriptor CreateEvent(Type componentType, EventDescriptor oldEventDescriptor, params Attribute[] attributes)
  498.         {
  499.             return new ReflectEventDescriptor(componentType, oldEventDescriptor, attributes);
  500.         }
  501.        
  502.         /// <devdoc>
  503.         /// This method will search internal tables within TypeDescriptor for
  504.         /// a TypeDescriptionProvider object that is associated with the given
  505.         /// data type. If it finds one, it will delegate the call to that object.
  506.         /// </devdoc>
  507.         public static object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
  508.         {
  509.             if (objectType == null) {
  510.                 throw new ArgumentNullException("objectType");
  511.             }
  512.            
  513.             if (argTypes != null) {
  514.                 if (args == null) {
  515.                     throw new ArgumentNullException("args");
  516.                 }
  517.                
  518.                 if (argTypes.Length != args.Length) {
  519.                     throw new ArgumentException(SR.GetString(SR.TypeDescriptorArgsCountMismatch));
  520.                 }
  521.             }
  522.            
  523.             object instance = null;
  524.            
  525.             // See if the provider wants to offer a TypeDescriptionProvider to delegate to. This allows
  526.             // a caller to have complete control over all object instantiation.
  527.             if (provider != null) {
  528.                 TypeDescriptionProvider p = provider.GetService(typeof(TypeDescriptionProvider)) as TypeDescriptionProvider;
  529.                 if (p != null) {
  530.                     instance = p.CreateInstance(provider, objectType, argTypes, args);
  531.                 }
  532.             }
  533.            
  534.             if (instance == null) {
  535.                 instance = NodeFor(objectType).CreateInstance(provider, objectType, argTypes, args);
  536.             }
  537.            
  538.             return instance;
  539.         }
  540.        
  541.         /// <devdoc>
  542.         /// This dynamically binds a PropertyDescriptor to a type.
  543.         /// </devdoc>
  544.         [ReflectionPermission(SecurityAction.LinkDemand, Flags = ReflectionPermissionFlag.MemberAccess)]
  545.         public static PropertyDescriptor CreateProperty(Type componentType, string name, Type type, params Attribute[] attributes)
  546.         {
  547.             return new ReflectPropertyDescriptor(componentType, name, type, attributes);
  548.         }
  549.        
  550.         /// <devdoc>
  551.         /// This creates a new property descriptor identical to an existing property descriptor. The new property descriptor
  552.         /// has the specified metadata attributes merged with the existing metadata attributes.
  553.         /// </devdoc>
  554.         [ReflectionPermission(SecurityAction.LinkDemand, Flags = ReflectionPermissionFlag.MemberAccess)]
  555.         public static PropertyDescriptor CreateProperty(Type componentType, PropertyDescriptor oldPropertyDescriptor, params Attribute[] attributes)
  556.         {
  557.            
  558.             // We must do some special case work here for extended properties. If the old property descriptor is really
  559.             // an extender property that is being surfaced on a component as a normal property, then we must
  560.             // do work here or else ReflectPropertyDescriptor will fail to resolve the get and set methods. We check
  561.             // for the necessary ExtenderProvidedPropertyAttribute and if we find it, we create an
  562.             // ExtendedPropertyDescriptor instead. We only do this if the component class is the same, since the user
  563.             // may want to re-route the property to a different target.
  564.             //
  565.             if (componentType == oldPropertyDescriptor.ComponentType) {
  566.                 ExtenderProvidedPropertyAttribute attr = (ExtenderProvidedPropertyAttribute)oldPropertyDescriptor.Attributes[typeof(ExtenderProvidedPropertyAttribute)];
  567.                
  568.                 ReflectPropertyDescriptor reflectDesc = attr.ExtenderProperty as ReflectPropertyDescriptor;
  569.                 if (reflectDesc != null) {
  570.                     return new ExtendedPropertyDescriptor(oldPropertyDescriptor, attributes);
  571.                 }
  572.                 #if DEBUG
  573.                 else {
  574.                     DebugReflectPropertyDescriptor debugReflectDesc = attr.ExtenderProperty as DebugReflectPropertyDescriptor;
  575.                     if (debugReflectDesc != null) {
  576.                         return new DebugExtendedPropertyDescriptor(oldPropertyDescriptor, attributes);
  577.                     }
  578.                 }
  579.                 #endif
  580.             }
  581.            
  582.             // This is either a normal prop or the caller has changed target classes.
  583.             //
  584.             return new ReflectPropertyDescriptor(componentType, oldPropertyDescriptor, attributes);
  585.         }
  586.        
  587.         /// <devdoc>
  588.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  589.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  590.         /// if the two type descriptors do not agree. This method returns true if
  591.         /// validation should be performed for the type.
  592.         /// </devdoc>
  593.         #if DEBUG
  594.         private static bool DebugShouldValidate(object key)
  595.         {
  596.             // Check our switch first.
  597.             //
  598.             if (EnableValidation.Enabled) {
  599.                 while (key != null) {
  600.                     // We only validate if there are no custom providers all the way
  601.                     // up the class chain.
  602.                     TypeDescriptionNode node = _providerTable[key] as TypeDescriptionNode;
  603.                     if (node != null && !(node.Provider is ReflectTypeDescriptionProvider)) {
  604.                         return false;
  605.                     }
  606.                    
  607.                     if (key is Type) {
  608.                         key = ((Type)key).BaseType;
  609.                     }
  610.                     else {
  611.                         key = key.GetType();
  612.                         if (((Type)key).IsCOMObject) {
  613.                             key = ComObjectType;
  614.                         }
  615.                     }
  616.                 }
  617.                 return true;
  618.             }
  619.             return false;
  620.         }
  621.         #endif
  622.        
  623.         /// <devdoc>
  624.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  625.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  626.         /// if the two type descriptors do not agree.
  627.         /// </devdoc>
  628.         [Conditional("DEBUG")]
  629.         private static void DebugValidate(Type type, AttributeCollection attributes, AttributeCollection debugAttributes)
  630.         {
  631.             #if DEBUG
  632.             if (!DebugShouldValidate(type))
  633.                 return;
  634.             DebugValidate(attributes, debugAttributes);
  635.             #endif
  636.         }
  637.        
  638.         /// <devdoc>
  639.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  640.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  641.         /// if the two type descriptors do not agree.
  642.         /// </devdoc>
  643.         [Conditional("DEBUG")]
  644.         private static void DebugValidate(AttributeCollection attributes, AttributeCollection debugAttributes)
  645.         {
  646.             #if DEBUG
  647.            
  648.             if (attributes.Count >= debugAttributes.Count) {
  649.                 foreach (Attribute a in attributes) {
  650.                     if (!(a is GuidAttribute) && !(a is ComVisibleAttribute)) {
  651.                         bool found = false;
  652.                         bool typeFound = false;
  653.                        
  654.                         // Many attributes don't implement .Equals correctly,
  655.                         // so they will fail an equality check. But we want to
  656.                         // make sure that common ones like Browsable and ReadOnly
  657.                         // were correctly picked up. So only check the ones in
  658.                         // component model.
  659.                         if (!a.GetType().FullName.StartsWith("System.Component")) {
  660.                             found = true;
  661.                             break;
  662.                         }
  663.                        
  664.                         if (!found) {
  665.                             foreach (Attribute b in debugAttributes) {
  666.                                 if (!typeFound && a.GetType() == b.GetType()) {
  667.                                     typeFound = true;
  668.                                 }
  669.                                
  670.                                 // Semitrust may throw here.
  671.                                 try {
  672.                                     if (a.Equals(b)) {
  673.                                         found = true;
  674.                                         break;
  675.                                     }
  676.                                 }
  677.                                 catch {
  678.                                     found = true;
  679.                                     break;
  680.                                 }
  681.                             }
  682.                         }
  683.                        
  684.                         if (!found && !a.IsDefaultAttribute()) {
  685.                             if (typeFound) {
  686.                                 Debug.Fail(string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Attribute {0} was found but failed equality. Perhaps attribute .Equals is not implemented correctly?", a.GetType().Name));
  687.                             }
  688.                             else {
  689.                                 Debug.Fail(string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Attribute {0} should not exist", a.GetType().Name));
  690.                             }
  691.                         }
  692.                     }
  693.                 }
  694.             }
  695.             else {
  696.                 foreach (Attribute b in debugAttributes) {
  697.                     // We skip all interop attributes because interface merging has changed on purpose.
  698.                     if (!(b is GuidAttribute) && !(b is ComVisibleAttribute) && !(b is InterfaceTypeAttribute) && !(b is ReadOnlyAttribute)) {
  699.                         bool found = false;
  700.                         bool typeFound = false;
  701.                        
  702.                         // Many attributes don't implement .Equals correctly,
  703.                         // so they will fail an equality check. But we want to
  704.                         // make sure that common ones like Browsable and ReadOnly
  705.                         // were correctly picked up. So only check the ones in
  706.                         // component model.
  707.                         if (!b.GetType().FullName.StartsWith("System.Component")) {
  708.                             found = true;
  709.                             break;
  710.                         }
  711.                        
  712.                         if (!found) {
  713.                             foreach (Attribute a in attributes) {
  714.                                 if (!typeFound && a.GetType() == b.GetType()) {
  715.                                     typeFound = true;
  716.                                 }
  717.                                
  718.                                 // Semitrust may throw here.
  719.                                 try {
  720.                                     if (b.Equals(a)) {
  721.                                         found = true;
  722.                                         break;
  723.                                     }
  724.                                 }
  725.                                 catch {
  726.                                     found = true;
  727.                                     break;
  728.                                 }
  729.                             }
  730.                         }
  731.                        
  732.                         if (!found && !b.IsDefaultAttribute()) {
  733.                             if (!typeFound) {
  734.                                 Debug.Fail(string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Attribute {0} should exist", b.GetType().Name));
  735.                             }
  736.                         }
  737.                     }
  738.                 }
  739.             }
  740.             #endif
  741.         }
  742.        
  743.         /// <devdoc>
  744.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  745.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  746.         /// if the two type descriptors do not agree.
  747.         /// </devdoc>
  748.         [Conditional("DEBUG")]
  749.         private static void DebugValidate(AttributeCollection attributes, Type type)
  750.         {
  751.             #if DEBUG
  752.             if (!DebugShouldValidate(type))
  753.                 return;
  754.             AttributeCollection debugAttributes = DebugTypeDescriptor.GetAttributes(type);
  755.             DebugValidate(attributes, debugAttributes);
  756.             #endif
  757.         }
  758.        
  759.         /// <devdoc>
  760.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  761.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  762.         /// if the two type descriptors do not agree.
  763.         /// </devdoc>
  764.         [Conditional("DEBUG")]
  765.         private static void DebugValidate(AttributeCollection attributes, object instance, bool noCustomTypeDesc)
  766.         {
  767.             #if DEBUG
  768.             if (!DebugShouldValidate(instance))
  769.                 return;
  770.             AttributeCollection debugAttributes = DebugTypeDescriptor.GetAttributes(instance, noCustomTypeDesc);
  771.             DebugValidate(attributes, debugAttributes);
  772.             #endif
  773.         }
  774.        
  775.         /// <devdoc>
  776.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  777.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  778.         /// if the two type descriptors do not agree.
  779.         /// </devdoc>
  780.         [Conditional("DEBUG")]
  781.         private static void DebugValidate(TypeConverter converter, Type type)
  782.         {
  783.             #if DEBUG
  784.             if (!DebugShouldValidate(type))
  785.                 return;
  786.             TypeConverter debugConverter = DebugTypeDescriptor.GetConverter(type);
  787.             Debug.Assert(debugConverter.GetType() == converter.GetType(), "TypeDescriptor engine Validation Failure.");
  788.             #endif
  789.         }
  790.        
  791.         /// <devdoc>
  792.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  793.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  794.         /// if the two type descriptors do not agree.
  795.         /// </devdoc>
  796.         [Conditional("DEBUG")]
  797.         private static void DebugValidate(TypeConverter converter, object instance, bool noCustomTypeDesc)
  798.         {
  799.             #if DEBUG
  800.             if (!DebugShouldValidate(instance))
  801.                 return;
  802.             TypeConverter debugConverter = DebugTypeDescriptor.GetConverter(instance, noCustomTypeDesc);
  803.             Debug.Assert(debugConverter.GetType() == converter.GetType(), "TypeDescriptor engine Validation Failure.");
  804.             #endif
  805.         }
  806.        
  807.         /// <devdoc>
  808.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  809.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  810.         /// if the two type descriptors do not agree.
  811.         /// </devdoc>
  812.         [Conditional("DEBUG")]
  813.         private static void DebugValidate(EventDescriptorCollection events, Type type, Attribute[] attributes)
  814.         {
  815.             #if DEBUG
  816.             if (!DebugShouldValidate(type))
  817.                 return;
  818.             EventDescriptorCollection debugEvents = DebugTypeDescriptor.GetEvents(type, attributes);
  819.             Debug.Assert(debugEvents.Count == events.Count, "TypeDescriptor engine Validation Failure. Event counts differ.");
  820.             foreach (EventDescriptor debugEvt in debugEvents) {
  821.                 EventDescriptor evt = null;
  822.                
  823.                 foreach (EventDescriptor realEvt in events) {
  824.                     if (realEvt.Name.Equals(debugEvt.Name) && realEvt.EventType == debugEvt.EventType && realEvt.ComponentType == debugEvt.ComponentType) {
  825.                         evt = realEvt;
  826.                         break;
  827.                     }
  828.                 }
  829.                
  830.                 Debug.Assert(evt != null, "TypeDescriptor engine Validation Failure. Event " + debugEvt.Name + " does not exist or is of the wrong type.");
  831.                 if (evt != null) {
  832.                     AttributeCollection attrs = evt.Attributes;
  833.                     if (attrs[typeof(AttributeProviderAttribute)] == null) {
  834.                         AttributeCollection debugAttrs = debugEvt.Attributes;
  835.                         DebugValidate(evt.EventType, attrs, debugAttrs);
  836.                     }
  837.                 }
  838.             }
  839.             #endif
  840.         }
  841.        
  842.         /// <devdoc>
  843.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  844.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  845.         /// if the two type descriptors do not agree.
  846.         /// </devdoc>
  847.         [Conditional("DEBUG")]
  848.         private static void DebugValidate(EventDescriptorCollection events, object instance, Attribute[] attributes, bool noCustomTypeDesc)
  849.         {
  850.             #if DEBUG
  851.             if (!DebugShouldValidate(instance))
  852.                 return;
  853.             EventDescriptorCollection debugEvents = DebugTypeDescriptor.GetEvents(instance, attributes, noCustomTypeDesc);
  854.             Debug.Assert(debugEvents.Count == events.Count, "TypeDescriptor engine Validation Failure. Event counts differ.");
  855.             foreach (EventDescriptor debugEvt in debugEvents) {
  856.                 EventDescriptor evt = null;
  857.                
  858.                 foreach (EventDescriptor realEvt in events) {
  859.                     if (realEvt.Name.Equals(debugEvt.Name) && realEvt.EventType == debugEvt.EventType && realEvt.ComponentType == debugEvt.ComponentType) {
  860.                         evt = realEvt;
  861.                         break;
  862.                     }
  863.                 }
  864.                
  865.                 Debug.Assert(evt != null, "TypeDescriptor engine Validation Failure. Event " + debugEvt.Name + " does not exist or is of the wrong type.");
  866.                 if (evt != null) {
  867.                     AttributeCollection attrs = evt.Attributes;
  868.                     if (attrs[typeof(AttributeProviderAttribute)] == null) {
  869.                         AttributeCollection debugAttrs = debugEvt.Attributes;
  870.                         DebugValidate(evt.EventType, attrs, debugAttrs);
  871.                     }
  872.                 }
  873.             }
  874.             #endif
  875.         }
  876.        
  877.         /// <devdoc>
  878.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  879.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  880.         /// if the two type descriptors do not agree.
  881.         /// </devdoc>
  882.         [Conditional("DEBUG")]
  883.         private static void DebugValidate(PropertyDescriptorCollection properties, Type type, Attribute[] attributes)
  884.         {
  885.             #if DEBUG
  886.             if (!DebugShouldValidate(type))
  887.                 return;
  888.             PropertyDescriptorCollection debugProperties = DebugTypeDescriptor.GetProperties(type, attributes);
  889.            
  890.             if (debugProperties.Count > properties.Count) {
  891.                 foreach (PropertyDescriptor debugProp in debugProperties) {
  892.                     PropertyDescriptor prop = null;
  893.                    
  894.                     foreach (PropertyDescriptor realProp in properties) {
  895.                         if (realProp.Name.Equals(debugProp.Name) && realProp.PropertyType == debugProp.PropertyType && realProp.ComponentType == debugProp.ComponentType) {
  896.                             prop = realProp;
  897.                             break;
  898.                         }
  899.                     }
  900.                    
  901.                     if (prop == null) {
  902.                         Debug.Fail(string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Property {0} of type {1} should exist.", debugProp.Name, debugProp.GetType().Name));
  903.                     }
  904.                 }
  905.             }
  906.             else if (properties.Count > debugProperties.Count) {
  907.                 foreach (PropertyDescriptor prop in properties) {
  908.                     PropertyDescriptor debugProp = null;
  909.                    
  910.                     foreach (PropertyDescriptor realProp in debugProperties) {
  911.                         if (realProp.Name.Equals(prop.Name) && realProp.PropertyType == prop.PropertyType && realProp.ComponentType == prop.ComponentType) {
  912.                             debugProp = realProp;
  913.                             break;
  914.                         }
  915.                     }
  916.                    
  917.                     if (debugProp == null) {
  918.                         Debug.Fail(string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Property {0} of type {1} should not exist.", prop.Name, prop.GetType().Name));
  919.                     }
  920.                 }
  921.             }
  922.             else {
  923.                 foreach (PropertyDescriptor debugProp in debugProperties) {
  924.                     PropertyDescriptor prop = null;
  925.                    
  926.                     foreach (PropertyDescriptor realProp in properties) {
  927.                         if (realProp.Name.Equals(debugProp.Name) && realProp.PropertyType == debugProp.PropertyType && realProp.ComponentType == debugProp.ComponentType) {
  928.                             prop = realProp;
  929.                             break;
  930.                         }
  931.                     }
  932.                    
  933.                     Debug.Assert(prop != null, string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Property {0} of type {1} exists but perhaps type mismatched?", debugProp.Name, debugProp.GetType().Name));
  934.                     if (prop != null) {
  935.                         AttributeCollection attrs = prop.Attributes;
  936.                         if (attrs[typeof(AttributeProviderAttribute)] == null) {
  937.                             AttributeCollection debugAttrs = debugProp.Attributes;
  938.                             DebugValidate(prop.PropertyType, attrs, debugAttrs);
  939.                         }
  940.                     }
  941.                 }
  942.             }
  943.             #endif
  944.         }
  945.        
  946.         /// <devdoc>
  947.         /// Debug code that runs the output of a TypeDescriptor query into a debug
  948.         /// type descriptor that uses the V1.0 algorithm. This code will assert
  949.         /// if the two type descriptors do not agree.
  950.         /// </devdoc>
  951.         [Conditional("DEBUG")]
  952.         private static void DebugValidate(PropertyDescriptorCollection properties, object instance, Attribute[] attributes, bool noCustomTypeDesc)
  953.         {
  954.             #if DEBUG
  955.             if (!DebugShouldValidate(instance))
  956.                 return;
  957.             PropertyDescriptorCollection debugProperties = DebugTypeDescriptor.GetProperties(instance, attributes, noCustomTypeDesc);
  958.            
  959.             if (debugProperties.Count > properties.Count) {
  960.                 foreach (PropertyDescriptor debugProp in debugProperties) {
  961.                     PropertyDescriptor prop = null;
  962.                    
  963.                     foreach (PropertyDescriptor realProp in properties) {
  964.                         if (realProp.Name.Equals(debugProp.Name) && realProp.PropertyType == debugProp.PropertyType && realProp.ComponentType == debugProp.ComponentType) {
  965.                             prop = realProp;
  966.                             break;
  967.                         }
  968.                     }
  969.                    
  970.                     if (prop == null) {
  971.                         Debug.Fail(string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Property {0} of type {1} should exist.", debugProp.Name, debugProp.GetType().Name));
  972.                     }
  973.                 }
  974.             }
  975.             else if (properties.Count > debugProperties.Count) {
  976.                 foreach (PropertyDescriptor prop in properties) {
  977.                     PropertyDescriptor debugProp = null;
  978.                    
  979.                     foreach (PropertyDescriptor realProp in debugProperties) {
  980.                         if (realProp.Name.Equals(prop.Name) && realProp.PropertyType == prop.PropertyType && realProp.ComponentType == prop.ComponentType) {
  981.                             debugProp = realProp;
  982.                             break;
  983.                         }
  984.                     }
  985.                    
  986.                     if (debugProp == null) {
  987.                         Debug.Fail(string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Property {0} of type {1} should not exist.", prop.Name, prop.GetType().Name));
  988.                     }
  989.                 }
  990.             }
  991.             else {
  992.                 foreach (PropertyDescriptor debugProp in debugProperties) {
  993.                     PropertyDescriptor prop = null;
  994.                    
  995.                     foreach (PropertyDescriptor realProp in properties) {
  996.                         if (realProp.Name.Equals(debugProp.Name) && realProp.PropertyType == debugProp.PropertyType && realProp.ComponentType == debugProp.ComponentType) {
  997.                             prop = realProp;
  998.                             break;
  999.                         }
  1000.                     }
  1001.                    
  1002.                     Debug.Assert(prop != null, string.Format(CultureInfo.InvariantCulture, "TypeDescriptor engine Validation Failure. Property {0} of type {1} exists but perhaps type mismatched?", debugProp.Name, debugProp.GetType().Name));
  1003.                     if (prop != null) {
  1004.                         AttributeCollection attrs = prop.Attributes;
  1005.                         if (attrs[typeof(AttributeProviderAttribute)] == null) {
  1006.                             AttributeCollection debugAttrs = debugProp.Attributes;
  1007.                             DebugValidate(prop.PropertyType, attrs, debugAttrs);
  1008.                         }
  1009.                     }
  1010.                 }
  1011.             }
  1012.             #endif
  1013.         }
  1014.        
  1015.         /// <devdoc>
  1016.         /// This API is used to remove any members from the given
  1017.         /// collection that do not match the attribute array. If members
  1018.         /// need to be removed, a new ArrayList wil be created that
  1019.         /// contains only the remaining members. The API returns
  1020.         /// NULL if it did not need to filter any members.
  1021.         /// </devdoc>
  1022.         private static ArrayList FilterMembers(IList members, Attribute[] attributes)
  1023.         {
  1024.             ArrayList newMembers = null;
  1025.             int memberCount = members.Count;
  1026.            
  1027.             for (int idx = 0; idx < memberCount; idx++) {
  1028.                
  1029.                 bool hide = false;
  1030.                
  1031.                 for (int attrIdx = 0; attrIdx < attributes.Length; attrIdx++) {
  1032.                     if (ShouldHideMember((MemberDescriptor)members[idx], attributes[attrIdx])) {
  1033.                         hide = true;
  1034.                         break;
  1035.                     }
  1036.                 }
  1037.                
  1038.                 if (hide) {
  1039.                     // We have to hide. If this is the first time, we need to init
  1040.                     // newMembers to have all the valid members we have previously
  1041.                     // hit.
  1042.                     if (newMembers == null) {
  1043.                         newMembers = new ArrayList(memberCount);
  1044.                         for (int validIdx = 0; validIdx < idx; validIdx++) {
  1045.                             newMembers.Add(members[validIdx]);
  1046.                         }
  1047.                     }
  1048.                 }
  1049.                 else if (newMembers != null) {
  1050.                     newMembers.Add(members[idx]);
  1051.                 }
  1052.                
  1053.             }
  1054.            
  1055.             return newMembers;
  1056.         }
  1057.        
  1058.         /// <devdoc>
  1059.         /// The GetAssociation method returns the correct object to invoke
  1060.         /// for the requested type. It never returns null.
  1061.         /// </devdoc>
  1062.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1063.         public static object GetAssociation(Type type, object primary)
  1064.         {
  1065.             if (type == null) {
  1066.                 throw new ArgumentNullException("type");
  1067.             }
  1068.            
  1069.             if (primary == null) {
  1070.                 throw new ArgumentNullException("primary");
  1071.             }
  1072.            
  1073.             object associatedObject = primary;
  1074.            
  1075.             if (!type.IsInstanceOfType(primary)) {
  1076.                 // Check our association table for a match.
  1077.                 //
  1078.                 Hashtable assocTable = _associationTable;
  1079.                 if (assocTable != null) {
  1080.                     IList associations = (IList)assocTable[primary];
  1081.                     if (associations != null) {
  1082.                         lock (associations) {
  1083.                             for (int idx = associations.Count - 1; idx >= 0; idx--) {
  1084.                                 // Look for an associated object that has a type that
  1085.                                 // matches the given type.
  1086.                                 //
  1087.                                 WeakReference weakRef = (WeakReference)associations[idx];
  1088.                                 object secondary = weakRef.Target;
  1089.                                 if (secondary == null) {
  1090.                                     Trace("Associations : Removing dead reference in assocation table");
  1091.                                     associations.RemoveAt(idx);
  1092.                                 }
  1093.                                 else if (type.IsInstanceOfType(secondary)) {
  1094.                                     Trace("Associations : Associated {0} to {1}", primary.GetType().Name, secondary.GetType().Name);
  1095.                                     associatedObject = secondary;
  1096.                                 }
  1097.                             }
  1098.                         }
  1099.                     }
  1100.                 }
  1101.                
  1102.                 // Not in our table. We have a default association with a designer
  1103.                 // if that designer is a component.
  1104.                 //
  1105.                 if (associatedObject == primary) {
  1106.                     IComponent component = primary as IComponent;
  1107.                     if (component != null) {
  1108.                         ISite site = component.Site;
  1109.                        
  1110.                         if (site != null && site.DesignMode) {
  1111.                             IDesignerHost host = site.GetService(typeof(IDesignerHost)) as IDesignerHost;
  1112.                             if (host != null) {
  1113.                                 object designer = host.GetDesigner(component);
  1114.                                
  1115.                                 // We only use the designer if it has a compatible class. If we
  1116.                                 // got here, we're probably hosed because the user just passed in
  1117.                                 // an object that this PropertyDescriptor can't munch on, but it's
  1118.                                 // clearer to use that object instance instead of it's designer.
  1119.                                 //
  1120.                                 if (designer != null && type.IsInstanceOfType(designer)) {
  1121.                                     Trace("Associations : Associated {0} to {1}", primary.GetType().Name, designer.GetType().Name);
  1122.                                     associatedObject = designer;
  1123.                                 }
  1124.                             }
  1125.                         }
  1126.                     }
  1127.                 }
  1128.             }
  1129.            
  1130.             return associatedObject;
  1131.         }
  1132.        
  1133.         /// <devdoc>
  1134.         /// Gets a collection of attributes for the specified type of component.
  1135.         /// </devdoc>
  1136.         public static AttributeCollection GetAttributes(Type componentType)
  1137.         {
  1138.             if (componentType == null) {
  1139.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1140.                 return new AttributeCollection((Attribute[])null);
  1141.             }
  1142.            
  1143.             AttributeCollection attributes = GetDescriptor(componentType, "componentType").GetAttributes();
  1144.             DebugValidate(attributes, componentType);
  1145.             return attributes;
  1146.         }
  1147.        
  1148.         /// <devdoc>
  1149.         /// Gets a collection of attributes for the specified component.
  1150.         /// </devdoc>
  1151.         public static AttributeCollection GetAttributes(object component)
  1152.         {
  1153.             return GetAttributes(component, false);
  1154.         }
  1155.        
  1156.         /// <devdoc>
  1157.         /// Gets a collection of attributes for the specified component.
  1158.         /// </devdoc>
  1159.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1160.         public static AttributeCollection GetAttributes(object component, bool noCustomTypeDesc)
  1161.         {
  1162.             if (component == null) {
  1163.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1164.                 return new AttributeCollection((Attribute[])null);
  1165.             }
  1166.            
  1167.             // We create a sort of pipeline for mucking with metadata. The pipeline
  1168.             // goes through the following process:
  1169.             //
  1170.             // 1. Merge metadata from extenders.
  1171.             // 2. Allow services to filter the metadata
  1172.             // 3. If an attribute filter was specified, apply that.
  1173.             //
  1174.             // The goal here is speed. We get speed by not copying or
  1175.             // allocating memory. We do this by allowing each phase of the
  1176.             // pipeline to cache its data in the object cache. If
  1177.             // a phase makes a change to the results, this change must cause
  1178.             // successive phases to recompute their results as well. "Results" is
  1179.             // always a collection, and the various stages of the pipeline may
  1180.             // replace or modify this collection (depending on if it's a
  1181.             // read-only IList or not). It is possible for the orignal
  1182.             // descriptor or attribute collection to pass through the entire
  1183.             // pipeline without modification.
  1184.             //
  1185.             ICustomTypeDescriptor typeDesc = GetDescriptor(component, noCustomTypeDesc);
  1186.             ICollection results = typeDesc.GetAttributes();
  1187.            
  1188.             // If we are handed a custom type descriptor we have several choices of action
  1189.             // we can take. If noCustomTypeDesc is true, it means that the custom type
  1190.             // descriptor is trying to find a baseline set of properties. In this case
  1191.             // we should merge in extended properties, but we do not let designers filter
  1192.             // because we're not done with the property set yet. If noCustomTypeDesc
  1193.             // is false, we don't do extender properties because the custom type descriptor
  1194.             // has already added them. In this case, we are doing a final pass so we
  1195.             // want to apply filtering. Finally, if the incoming object is not a custom
  1196.             // type descriptor, we do extenders and the filter.
  1197.             //
  1198.             if (component is ICustomTypeDescriptor) {
  1199.                 if (noCustomTypeDesc) {
  1200.                     ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
  1201.                     if (extDesc != null) {
  1202.                         ICollection extResults = extDesc.GetAttributes();
  1203.                         results = PipelineMerge(PIPELINE_ATTRIBUTES, results, extResults, component, null);
  1204.                     }
  1205.                 }
  1206.                 else {
  1207.                     results = PipelineFilter(PIPELINE_ATTRIBUTES, results, component, null);
  1208.                 }
  1209.             }
  1210.             else {
  1211.                 IDictionary cache = GetCache(component);
  1212.                
  1213.                 results = PipelineInitialize(PIPELINE_ATTRIBUTES, results, cache);
  1214.                
  1215.                 ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
  1216.                 if (extDesc != null) {
  1217.                     ICollection extResults = extDesc.GetAttributes();
  1218.                     results = PipelineMerge(PIPELINE_ATTRIBUTES, results, extResults, component, cache);
  1219.                 }
  1220.                
  1221.                 results = PipelineFilter(PIPELINE_ATTRIBUTES, results, component, cache);
  1222.             }
  1223.            
  1224.             AttributeCollection attrs = results as AttributeCollection;
  1225.             if (attrs == null) {
  1226.                 Trace("Attributes : Allocated new attribute collection for {0}", component.GetType().Name);
  1227.                 Attribute[] attrArray = new Attribute[results.Count];
  1228.                 results.CopyTo(attrArray, 0);
  1229.                 attrs = new AttributeCollection(attrArray);
  1230.             }
  1231.            
  1232.             DebugValidate(attrs, component, noCustomTypeDesc);
  1233.             return attrs;
  1234.         }
  1235.        
  1236.         /// <devdoc>
  1237.         /// Helper function to obtain a cache for the given object.
  1238.         /// </devdoc>
  1239.         static internal IDictionary GetCache(object instance)
  1240.         {
  1241.             return NodeFor(instance).GetCache(instance);
  1242.         }
  1243.        
  1244.         /// <devdoc>
  1245.         /// Gets the name of the class for the specified component.
  1246.         /// </devdoc>
  1247.         public static string GetClassName(object component)
  1248.         {
  1249.             return GetClassName(component, false);
  1250.         }
  1251.        
  1252.         /// <devdoc>
  1253.         /// Gets the name of the class for the specified component.
  1254.         /// </devdoc>
  1255.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1256.         public static string GetClassName(object component, bool noCustomTypeDesc)
  1257.         {
  1258.             return GetDescriptor(component, noCustomTypeDesc).GetClassName();
  1259.         }
  1260.        
  1261.         /// <devdoc>
  1262.         /// Gets the name of the class for the specified type.
  1263.         /// </devdoc>
  1264.         public static string GetClassName(Type componentType)
  1265.         {
  1266.             return GetDescriptor(componentType, "componentType").GetClassName();
  1267.         }
  1268.        
  1269.         /// <devdoc>
  1270.         /// The name of the class for the specified component.
  1271.         /// </devdoc>
  1272.         public static string GetComponentName(object component)
  1273.         {
  1274.             return GetComponentName(component, false);
  1275.         }
  1276.        
  1277.         /// <devdoc>
  1278.         /// Gets the name of the class for the specified component.
  1279.         /// </devdoc>
  1280.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1281.         public static string GetComponentName(object component, bool noCustomTypeDesc)
  1282.         {
  1283.             return GetDescriptor(component, noCustomTypeDesc).GetComponentName();
  1284.         }
  1285.        
  1286.         /// <devdoc>
  1287.         /// Gets a type converter for the type of the specified component.
  1288.         /// </devdoc>
  1289.         public static TypeConverter GetConverter(object component)
  1290.         {
  1291.             return GetConverter(component, false);
  1292.         }
  1293.        
  1294.         /// <devdoc>
  1295.         /// Gets a type converter for the type of the specified component.
  1296.         /// </devdoc>
  1297.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1298.         public static TypeConverter GetConverter(object component, bool noCustomTypeDesc)
  1299.         {
  1300.             TypeConverter converter = GetDescriptor(component, noCustomTypeDesc).GetConverter();
  1301.             DebugValidate(converter, component, noCustomTypeDesc);
  1302.             return converter;
  1303.         }
  1304.        
  1305.         /// <devdoc>
  1306.         /// Gets a type converter for the specified type.
  1307.         /// </devdoc>
  1308.         [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
  1309.         public static TypeConverter GetConverter(Type type)
  1310.         {
  1311.             TypeConverter converter = GetDescriptor(type, "type").GetConverter();
  1312.             DebugValidate(converter, type);
  1313.             return converter;
  1314.         }
  1315.        
  1316.         /// <devdoc>
  1317.         /// Gets the default event for the specified type of component.
  1318.         /// </devdoc>
  1319.         public static EventDescriptor GetDefaultEvent(Type componentType)
  1320.         {
  1321.             if (componentType == null) {
  1322.                 Debug.Fail("COMPAT: Returning null, but you should not pass null here");
  1323.                 return null;
  1324.             }
  1325.            
  1326.             return GetDescriptor(componentType, "componentType").GetDefaultEvent();
  1327.         }
  1328.        
  1329.         /// <devdoc>
  1330.         /// Gets the default event for the specified component.
  1331.         /// </devdoc>
  1332.         public static EventDescriptor GetDefaultEvent(object component)
  1333.         {
  1334.             return GetDefaultEvent(component, false);
  1335.         }
  1336.        
  1337.         /// <devdoc>
  1338.         /// Gets the default event for a component.
  1339.         /// </devdoc>
  1340.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1341.         public static EventDescriptor GetDefaultEvent(object component, bool noCustomTypeDesc)
  1342.         {
  1343.             if (component == null) {
  1344.                 Debug.Fail("COMPAT: Returning null, but you should not pass null here");
  1345.                 return null;
  1346.             }
  1347.            
  1348.             return GetDescriptor(component, noCustomTypeDesc).GetDefaultEvent();
  1349.         }
  1350.        
  1351.         /// <devdoc>
  1352.         /// Gets the default property for the specified type of component.
  1353.         /// </devdoc>
  1354.         public static PropertyDescriptor GetDefaultProperty(Type componentType)
  1355.         {
  1356.             if (componentType == null) {
  1357.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1358.                 return null;
  1359.             }
  1360.            
  1361.             return GetDescriptor(componentType, "componentType").GetDefaultProperty();
  1362.         }
  1363.        
  1364.         /// <devdoc>
  1365.         /// Gets the default property for the specified component.
  1366.         /// </devdoc>
  1367.         public static PropertyDescriptor GetDefaultProperty(object component)
  1368.         {
  1369.             return GetDefaultProperty(component, false);
  1370.         }
  1371.        
  1372.         /// <devdoc>
  1373.         /// Gets the default property for the specified component.
  1374.         /// </devdoc>
  1375.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1376.         public static PropertyDescriptor GetDefaultProperty(object component, bool noCustomTypeDesc)
  1377.         {
  1378.             if (component == null) {
  1379.                 Debug.Fail("COMPAT: Returning null, but you should not pass null here");
  1380.                 return null;
  1381.             }
  1382.            
  1383.             return GetDescriptor(component, noCustomTypeDesc).GetDefaultProperty();
  1384.         }
  1385.        
  1386.         /// <devdoc>
  1387.         /// Returns a custom type descriptor for the given type.
  1388.         /// Performs arg checking so callers don't have to.
  1389.         /// </devdoc>
  1390.         static internal ICustomTypeDescriptor GetDescriptor(Type type, string typeName)
  1391.         {
  1392.             if (type == null) {
  1393.                 throw new ArgumentNullException(typeName);
  1394.             }
  1395.            
  1396.             return NodeFor(type).GetTypeDescriptor(type);
  1397.         }
  1398.        
  1399.         /// <devdoc>
  1400.         /// Returns a custom type descriptor for the given instance.
  1401.         /// Performs arg checking so callers don't have to. This
  1402.         /// will call through to instance if it is a custom type
  1403.         /// descriptor.
  1404.         /// </devdoc>
  1405.         static internal ICustomTypeDescriptor GetDescriptor(object component, bool noCustomTypeDesc)
  1406.         {
  1407.             if (component == null) {
  1408.                 throw new ArgumentException("component");
  1409.             }
  1410.            
  1411.             if (component is IUnimplemented) {
  1412.                 throw new NotSupportedException(SR.GetString(SR.TypeDescriptorUnsupportedRemoteObject, component.GetType().FullName));
  1413.             }
  1414.            
  1415.            
  1416.             ICustomTypeDescriptor desc = NodeFor(component).GetTypeDescriptor(component);
  1417.             ICustomTypeDescriptor d = component as ICustomTypeDescriptor;
  1418.             if (!noCustomTypeDesc && d != null) {
  1419.                 desc = new MergedTypeDescriptor(d, desc);
  1420.             }
  1421.            
  1422.             return desc;
  1423.         }
  1424.        
  1425.         /// <devdoc>
  1426.         /// Returns an extended custom type descriptor for the given instance.
  1427.         /// </devdoc>
  1428.         static internal ICustomTypeDescriptor GetExtendedDescriptor(object component)
  1429.         {
  1430.             if (component == null) {
  1431.                 throw new ArgumentException("component");
  1432.             }
  1433.            
  1434.             return NodeFor(component).GetExtendedTypeDescriptor(component);
  1435.         }
  1436.        
  1437.         /// <devdoc>
  1438.         /// Gets an editor with the specified base type for the
  1439.         /// specified component.
  1440.         /// </devdoc>
  1441.         public static object GetEditor(object component, Type editorBaseType)
  1442.         {
  1443.             return GetEditor(component, editorBaseType, false);
  1444.         }
  1445.        
  1446.         /// <devdoc>
  1447.         /// Gets an editor with the specified base type for the
  1448.         /// specified component.
  1449.         /// </devdoc>
  1450.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1451.         public static object GetEditor(object component, Type editorBaseType, bool noCustomTypeDesc)
  1452.         {
  1453.             if (editorBaseType == null) {
  1454.                 throw new ArgumentNullException("editorBaseType");
  1455.             }
  1456.            
  1457.             return GetDescriptor(component, noCustomTypeDesc).GetEditor(editorBaseType);
  1458.         }
  1459.        
  1460.         /// <devdoc>
  1461.         /// Gets an editor with the specified base type for the specified type.
  1462.         /// </devdoc>
  1463.         public static object GetEditor(Type type, Type editorBaseType)
  1464.         {
  1465.             if (editorBaseType == null) {
  1466.                 throw new ArgumentNullException("editorBaseType");
  1467.             }
  1468.            
  1469.             return GetDescriptor(type, "type").GetEditor(editorBaseType);
  1470.         }
  1471.        
  1472.         /// <devdoc>
  1473.         /// Gets a collection of events for a specified type of component.
  1474.         /// </devdoc>
  1475.         public static EventDescriptorCollection GetEvents(Type componentType)
  1476.         {
  1477.             if (componentType == null) {
  1478.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1479.                 return new EventDescriptorCollection(null, true);
  1480.             }
  1481.            
  1482.             return GetDescriptor(componentType, "componentType").GetEvents();
  1483.         }
  1484.        
  1485.         /// <devdoc>
  1486.         /// Gets a collection of events for a specified type of
  1487.         /// component using a specified array of attributes as a filter.
  1488.         /// </devdoc>
  1489.         public static EventDescriptorCollection GetEvents(Type componentType, Attribute[] attributes)
  1490.         {
  1491.             if (componentType == null) {
  1492.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1493.                 return new EventDescriptorCollection(null, true);
  1494.             }
  1495.            
  1496.             EventDescriptorCollection events = GetDescriptor(componentType, "componentType").GetEvents(attributes);
  1497.            
  1498.             if (attributes != null && attributes.Length > 0) {
  1499.                 ArrayList filteredEvents = FilterMembers(events, attributes);
  1500.                 if (filteredEvents != null) {
  1501.                     events = new EventDescriptorCollection((EventDescriptor[])filteredEvents.ToArray(typeof(EventDescriptor)), true);
  1502.                 }
  1503.             }
  1504.            
  1505.             DebugValidate(events, componentType, attributes);
  1506.             return events;
  1507.         }
  1508.        
  1509.         /// <devdoc>
  1510.         /// Gets a collection of events for a specified component.
  1511.         /// </devdoc>
  1512.         public static EventDescriptorCollection GetEvents(object component)
  1513.         {
  1514.             return GetEvents(component, null, false);
  1515.         }
  1516.        
  1517.         /// <devdoc>
  1518.         /// Gets a collection of events for a specified component.
  1519.         /// </devdoc>
  1520.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1521.         public static EventDescriptorCollection GetEvents(object component, bool noCustomTypeDesc)
  1522.         {
  1523.             return GetEvents(component, null, noCustomTypeDesc);
  1524.         }
  1525.        
  1526.         /// <devdoc>
  1527.         /// Gets a collection of events for a specified component
  1528.         /// using a specified array of attributes as a filter.
  1529.         /// </devdoc>
  1530.         public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes)
  1531.         {
  1532.             return GetEvents(component, attributes, false);
  1533.         }
  1534.        
  1535.         /// <devdoc>
  1536.         /// Gets a collection of events for a specified component
  1537.         /// using a specified array of attributes as a filter.
  1538.         /// </devdoc>
  1539.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1540.         public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes, bool noCustomTypeDesc)
  1541.         {
  1542.             if (component == null) {
  1543.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1544.                 return new EventDescriptorCollection(null, true);
  1545.             }
  1546.            
  1547.             // We create a sort of pipeline for mucking with metadata. The pipeline
  1548.             // goes through the following process:
  1549.             //
  1550.             // 1. Merge metadata from extenders.
  1551.             // 2. Allow services to filter the metadata
  1552.             // 3. If an attribute filter was specified, apply that.
  1553.             //
  1554.             // The goal here is speed. We get speed by not copying or
  1555.             // allocating memory. We do this by allowing each phase of the
  1556.             // pipeline to cache its data in the object cache. If
  1557.             // a phase makes a change to the results, this change must cause
  1558.             // successive phases to recompute their results as well. "Results" is
  1559.             // always a collection, and the various stages of the pipeline may
  1560.             // replace or modify this collection (depending on if it's a
  1561.             // read-only IList or not). It is possible for the orignal
  1562.             // descriptor or attribute collection to pass through the entire
  1563.             // pipeline without modification.
  1564.             //
  1565.             ICustomTypeDescriptor typeDesc = GetDescriptor(component, noCustomTypeDesc);
  1566.             ICollection results;
  1567.            
  1568.             // If we are handed a custom type descriptor we have several choices of action
  1569.             // we can take. If noCustomTypeDesc is true, it means that the custom type
  1570.             // descriptor is trying to find a baseline set of events. In this case
  1571.             // we should merge in extended events, but we do not let designers filter
  1572.             // because we're not done with the event set yet. If noCustomTypeDesc
  1573.             // is false, we don't do extender events because the custom type descriptor
  1574.             // has already added them. In this case, we are doing a final pass so we
  1575.             // want to apply filtering. Finally, if the incoming object is not a custom
  1576.             // type descriptor, we do extenders and the filter.
  1577.             //
  1578.             if (component is ICustomTypeDescriptor) {
  1579.                 results = typeDesc.GetEvents(attributes);
  1580.                 if (noCustomTypeDesc) {
  1581.                     ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
  1582.                     if (extDesc != null) {
  1583.                         ICollection extResults = extDesc.GetEvents(attributes);
  1584.                         results = PipelineMerge(PIPELINE_EVENTS, results, extResults, component, null);
  1585.                     }
  1586.                 }
  1587.                 else {
  1588.                     results = PipelineFilter(PIPELINE_EVENTS, results, component, null);
  1589.                     results = PipelineAttributeFilter(PIPELINE_EVENTS, results, attributes, component, null);
  1590.                 }
  1591.             }
  1592.             else {
  1593.                 IDictionary cache = GetCache(component);
  1594.                 results = typeDesc.GetEvents(attributes);
  1595.                 results = PipelineInitialize(PIPELINE_EVENTS, results, cache);
  1596.                 ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
  1597.                 if (extDesc != null) {
  1598.                     ICollection extResults = extDesc.GetEvents(attributes);
  1599.                     results = PipelineMerge(PIPELINE_EVENTS, results, extResults, component, cache);
  1600.                 }
  1601.                
  1602.                 results = PipelineFilter(PIPELINE_EVENTS, results, component, cache);
  1603.                 results = PipelineAttributeFilter(PIPELINE_EVENTS, results, attributes, component, cache);
  1604.             }
  1605.            
  1606.             EventDescriptorCollection evts = results as EventDescriptorCollection;
  1607.             if (evts == null) {
  1608.                 Trace("Events : Allocated new event collection for {0}", component.GetType().Name);
  1609.                 EventDescriptor[] eventArray = new EventDescriptor[results.Count];
  1610.                 results.CopyTo(eventArray, 0);
  1611.                 evts = new EventDescriptorCollection(eventArray, true);
  1612.             }
  1613.            
  1614.             DebugValidate(evts, component, attributes, noCustomTypeDesc);
  1615.            
  1616.             return evts;
  1617.         }
  1618.        
  1619.         /// <devdoc>
  1620.         /// This method is invoked during filtering when a name
  1621.         /// collision is encountered between two properties or events. This returns
  1622.         /// a suffix that can be appended to the name to make
  1623.         /// it unique. This will first attempt ot use the name of the
  1624.         /// extender. Failing that it will fall back to a static
  1625.         /// index that is continually incremented.
  1626.         /// </devdoc>
  1627.         private static string GetExtenderCollisionSuffix(MemberDescriptor member)
  1628.         {
  1629.             string suffix = null;
  1630.            
  1631.             ExtenderProvidedPropertyAttribute exAttr = member.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute;
  1632.             if (exAttr != null) {
  1633.                 IExtenderProvider prov = exAttr.Provider;
  1634.                
  1635.                 if (prov != null) {
  1636.                     string name = null;
  1637.                     IComponent component = prov as IComponent;
  1638.                    
  1639.                     if (component != null && component.Site != null) {
  1640.                         name = component.Site.Name;
  1641.                     }
  1642.                    
  1643.                     if (name == null || name.Length == 0) {
  1644.                         name = (_collisionIndex++).ToString(CultureInfo.InvariantCulture);
  1645.                     }
  1646.                    
  1647.                     suffix = string.Format(CultureInfo.InvariantCulture, "_{0}", name);
  1648.                 }
  1649.             }
  1650.            
  1651.             return suffix;
  1652.         }
  1653.        
  1654.         /// <devdoc>
  1655.         /// The name of the specified component, or null if the component has no name.
  1656.         /// In many cases this will return the same value as GetComponentName. If the
  1657.         /// component resides in a nested container or has other nested semantics, it may
  1658.         /// return a different fully qualfied name.
  1659.         /// </devdoc>
  1660.         public static string GetFullComponentName(object component)
  1661.         {
  1662.             if (component == null)
  1663.                 throw new ArgumentNullException("component");
  1664.             return GetProvider(component).GetFullComponentName(component);
  1665.         }
  1666.        
  1667.         /// <devdoc>
  1668.         /// Gets a collection of properties for a specified type of component.
  1669.         /// </devdoc>
  1670.         public static PropertyDescriptorCollection GetProperties(Type componentType)
  1671.         {
  1672.             if (componentType == null) {
  1673.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1674.                 return new PropertyDescriptorCollection(null, true);
  1675.             }
  1676.            
  1677.             return GetDescriptor(componentType, "componentType").GetProperties();
  1678.         }
  1679.        
  1680.         /// <devdoc>
  1681.         /// Gets a collection of properties for a specified type of
  1682.         /// component using a specified array of attributes as a filter.
  1683.         /// </devdoc>
  1684.         public static PropertyDescriptorCollection GetProperties(Type componentType, Attribute[] attributes)
  1685.         {
  1686.             if (componentType == null) {
  1687.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1688.                 return new PropertyDescriptorCollection(null, true);
  1689.             }
  1690.            
  1691.             PropertyDescriptorCollection properties = GetDescriptor(componentType, "componentType").GetProperties(attributes);
  1692.            
  1693.             if (attributes != null && attributes.Length > 0) {
  1694.                 ArrayList filteredProperties = FilterMembers(properties, attributes);
  1695.                 if (filteredProperties != null) {
  1696.                     properties = new PropertyDescriptorCollection((PropertyDescriptor[])filteredProperties.ToArray(typeof(PropertyDescriptor)), true);
  1697.                 }
  1698.             }
  1699.            
  1700.             DebugValidate(properties, componentType, attributes);
  1701.             return properties;
  1702.         }
  1703.        
  1704.         /// <devdoc>
  1705.         /// Gets a collection of properties for a specified component.
  1706.         /// </devdoc>
  1707.         public static PropertyDescriptorCollection GetProperties(object component)
  1708.         {
  1709.             return GetProperties(component, false);
  1710.         }
  1711.        
  1712.         /// <devdoc>
  1713.         /// Gets a collection of properties for a specified component.
  1714.         /// </devdoc>
  1715.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1716.         public static PropertyDescriptorCollection GetProperties(object component, bool noCustomTypeDesc)
  1717.         {
  1718.             return GetPropertiesImpl(component, null, noCustomTypeDesc, true);
  1719.         }
  1720.        
  1721.         /// <devdoc>
  1722.         /// Gets a collection of properties for a specified
  1723.         /// component using a specified array of attributes
  1724.         /// as a filter.
  1725.         /// </devdoc>
  1726.         public static PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes)
  1727.         {
  1728.             return GetProperties(component, attributes, false);
  1729.         }
  1730.        
  1731.         /// <devdoc>
  1732.         /// <para>Gets a collection of properties for a specified
  1733.         /// component using a specified array of attributes
  1734.         /// as a filter.</para>
  1735.         /// </devdoc>
  1736.         public static PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes, bool noCustomTypeDesc)
  1737.         {
  1738.             return GetPropertiesImpl(component, attributes, noCustomTypeDesc, false);
  1739.         }
  1740.        
  1741.         /// <devdoc>
  1742.         /// Gets a collection of properties for a specified component. Uses the attribute filter
  1743.         /// only if noAttributes is false. This is to preserve backward compat for the case when
  1744.         /// no attribute filter was passed in (as against passing in null).
  1745.         /// </devdoc>
  1746.         private static PropertyDescriptorCollection GetPropertiesImpl(object component, Attribute[] attributes, bool noCustomTypeDesc, bool noAttributes)
  1747.         {
  1748.             if (component == null) {
  1749.                 Debug.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
  1750.                 return new PropertyDescriptorCollection(null, true);
  1751.             }
  1752.            
  1753.             // We create a sort of pipeline for mucking with metadata. The pipeline
  1754.             // goes through the following process:
  1755.             //
  1756.             // 1. Merge metadata from extenders.
  1757.             // 2. Allow services to filter the metadata
  1758.             // 3. If an attribute filter was specified, apply that.
  1759.             //
  1760.             // The goal here is speed. We get speed by not copying or
  1761.             // allocating memory. We do this by allowing each phase of the
  1762.             // pipeline to cache its data in the object cache. If
  1763.             // a phase makes a change to the results, this change must cause
  1764.             // successive phases to recompute their results as well. "Results" is
  1765.             // always a collection, and the various stages of the pipeline may
  1766.             // replace or modify this collection (depending on if it's a
  1767.             // read-only IList or not). It is possible for the orignal
  1768.             // descriptor or attribute collection to pass through the entire
  1769.             // pipeline without modification.
  1770.             //
  1771.             ICustomTypeDescriptor typeDesc = GetDescriptor(component, noCustomTypeDesc);
  1772.             ICollection results;
  1773.            
  1774.             // If we are handed a custom type descriptor we have several choices of action
  1775.             // we can take. If noCustomTypeDesc is true, it means that the custom type
  1776.             // descriptor is trying to find a baseline set of properties. In this case
  1777.             // we should merge in extended properties, but we do not let designers filter
  1778.             // because we're not done with the property set yet. If noCustomTypeDesc
  1779.             // is false, we don't do extender properties because the custom type descriptor
  1780.             // has already added them. In this case, we are doing a final pass so we
  1781.             // want to apply filtering. Finally, if the incoming object is not a custom
  1782.             // type descriptor, we do extenders and the filter.
  1783.             //
  1784.             if (component is ICustomTypeDescriptor) {
  1785.                 results = noAttributes ? typeDesc.GetProperties() : typeDesc.GetProperties(attributes);
  1786.                 if (noCustomTypeDesc) {
  1787.                     ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
  1788.                     if (extDesc != null) {
  1789.                         ICollection extResults = noAttributes ? extDesc.GetProperties() : extDesc.GetProperties(attributes);
  1790.                         results = PipelineMerge(PIPELINE_PROPERTIES, results, extResults, component, null);
  1791.                     }
  1792.                 }
  1793.                 else {
  1794.                     results = PipelineFilter(PIPELINE_PROPERTIES, results, component, null);
  1795.                     results = PipelineAttributeFilter(PIPELINE_PROPERTIES, results, attributes, component, null);
  1796.                 }
  1797.             }
  1798.             else {
  1799.                 IDictionary cache = GetCache(component);
  1800.                 results = noAttributes ? typeDesc.GetProperties() : typeDesc.GetProperties(attributes);
  1801.                 results = PipelineInitialize(PIPELINE_PROPERTIES, results, cache);
  1802.                 ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
  1803.                 if (extDesc != null) {
  1804.                     ICollection extResults = noAttributes ? extDesc.GetProperties() : extDesc.GetProperties(attributes);
  1805.                     results = PipelineMerge(PIPELINE_PROPERTIES, results, extResults, component, cache);
  1806.                 }
  1807.                
  1808.                 results = PipelineFilter(PIPELINE_PROPERTIES, results, component, cache);
  1809.                 results = PipelineAttributeFilter(PIPELINE_PROPERTIES, results, attributes, component, cache);
  1810.             }
  1811.            
  1812.             PropertyDescriptorCollection props = results as PropertyDescriptorCollection;
  1813.             if (props == null) {
  1814.                 Trace("Properties : Allocated new property collection for {0}", component.GetType().Name);
  1815.                 PropertyDescriptor[] propArray = new PropertyDescriptor[results.Count];
  1816.                 results.CopyTo(propArray, 0);
  1817.                 props = new PropertyDescriptorCollection(propArray, true);
  1818.             }
  1819.            
  1820.             DebugValidate(props, component, attributes, noCustomTypeDesc);
  1821.            
  1822.             return props;
  1823.         }
  1824.        
  1825.         /// <devdoc>
  1826.         /// The GetProvider method returns a type description provider for
  1827.         /// the given object or type. This will always return a type description
  1828.         /// provider. Even the default TypeDescriptor implementation is built on
  1829.         /// a TypeDescriptionProvider, and this will be returned unless there is
  1830.         /// another provider that someone else has added.
  1831.         /// </devdoc>
  1832.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1833.         public static TypeDescriptionProvider GetProvider(Type type)
  1834.         {
  1835.             if (type == null) {
  1836.                 throw new ArgumentNullException("type");
  1837.             }
  1838.            
  1839.             return NodeFor(type, true);
  1840.         }
  1841.        
  1842.         /// <devdoc>
  1843.         /// The GetProvider method returns a type description provider for
  1844.         /// the given object or type. This will always return a type description
  1845.         /// provider. Even the default TypeDescriptor implementation is built on
  1846.         /// a TypeDescriptionProvider, and this will be returned unless there is
  1847.         /// another provider that someone else has added.
  1848.         /// </devdoc>
  1849.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1850.         public static TypeDescriptionProvider GetProvider(object instance)
  1851.         {
  1852.             if (instance == null) {
  1853.                 throw new ArgumentNullException("instance");
  1854.             }
  1855.            
  1856.             return NodeFor(instance, true);
  1857.         }
  1858.        
  1859.         /// <devdoc>
  1860.         /// This method returns a type description provider, but instead of creating
  1861.         /// a delegating provider for the type, this will walk all base types until
  1862.         /// it locates a provider. The provider returned cannot be cached. This
  1863.         /// method is used by the DelegatingTypeDescriptionProvider to efficiently
  1864.         /// locate the provider to delegate to.
  1865.         /// </devdoc>
  1866.         static internal TypeDescriptionProvider GetProviderRecursive(Type type)
  1867.         {
  1868.             return NodeFor(type, false);
  1869.         }
  1870.        
  1871.         /// <devdoc>
  1872.         /// Returns an Type instance that can be used to perform reflection.
  1873.         /// </devdoc>
  1874.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1875.         public static Type GetReflectionType(Type type)
  1876.         {
  1877.             if (type == null) {
  1878.                 throw new ArgumentNullException("type");
  1879.             }
  1880.            
  1881.             return NodeFor(type).GetReflectionType(type);
  1882.         }
  1883.        
  1884.         /// <devdoc>
  1885.         /// Returns an Type instance that can be used to perform reflection.
  1886.         /// </devdoc>
  1887.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  1888.         public static Type GetReflectionType(object instance)
  1889.         {
  1890.             if (instance == null) {
  1891.                 throw new ArgumentNullException("instance");
  1892.             }
  1893.            
  1894.             return NodeFor(instance).GetReflectionType(instance);
  1895.         }
  1896.        
  1897.         /// <devdoc>
  1898.         /// Retrieves the head type description node for a type.
  1899.         /// A head node pointing to a reflection based type description
  1900.         /// provider will be created on demand. This does not create
  1901.         /// a delegator, in which case the node returned may be
  1902.         /// a base type node.
  1903.         /// </devdoc>
  1904.         private static TypeDescriptionNode NodeFor(Type type)
  1905.         {
  1906.             return NodeFor(type, false);
  1907.         }
  1908.        
  1909.         /// <devdoc>
  1910.         /// Retrieves the head type description node for a type.
  1911.         /// A head node pointing to a reflection based type description
  1912.         /// provider will be created on demand.
  1913.         ///
  1914.         /// If createDelegator is true, this method will create a delegation
  1915.         /// node for a type if the type has no node of its own. Delegation
  1916.         /// nodes should be created if you are going to hand this node
  1917.         /// out to a user. Without a delegation node, user code could
  1918.         /// skip providers that are added after their call. Delegation
  1919.         /// nodes solve that problem.
  1920.         ///
  1921.         /// If createDelegator is false, this method will recurse up the
  1922.         /// base type chain looking for nodes.
  1923.         /// </devdoc>
  1924.         private static TypeDescriptionNode NodeFor(Type type, bool createDelegator)
  1925.         {
  1926.             Debug.Assert(type != null, "Caller should validate");
  1927.             CheckDefaultProvider(type);
  1928.            
  1929.             // First, check our provider type table to see if we have a matching
  1930.             // provider for this type. The provider type table is a cache that
  1931.             // matches types to providers. When a new provider is added or
  1932.             // an existing one removed, the provider type table is torn
  1933.             // down and automatically rebuilt on demand.
  1934.             //
  1935.             TypeDescriptionNode node = null;
  1936.             Type searchType = type;
  1937.            
  1938.             while (node == null) {
  1939.                
  1940.                 node = (TypeDescriptionNode)_providerTypeTable[searchType];
  1941.                 if (node == null) {
  1942.                     node = (TypeDescriptionNode)_providerTable[searchType];
  1943.                 }
  1944.                
  1945.                 if (node == null) {
  1946.                     Type baseType = searchType.BaseType;
  1947.                    
  1948.                     if (searchType == typeof(object) || baseType == null) {
  1949.                         lock (_providerTable) {
  1950.                             node = (TypeDescriptionNode)_providerTable[searchType];
  1951.                            
  1952.                             if (node == null) {
  1953.                                 // The reflect type description provider is a default provider that
  1954.                                 // can provide type information for all objects.
  1955.                                 node = new TypeDescriptionNode(new ReflectTypeDescriptionProvider());
  1956.                                 _providerTable[searchType] = node;
  1957.                                 Trace("Nodes : Allocated new type node. Now {0} nodes", _providerTable.Count);
  1958.                             }
  1959.                         }
  1960.                     }
  1961.                     else if (createDelegator) {
  1962.                         node = new TypeDescriptionNode(new DelegatingTypeDescriptionProvider(baseType));
  1963.                         _providerTypeTable[searchType] = node;
  1964.                     }
  1965.                     else {
  1966.                         // Continue our search
  1967.                         searchType = baseType;
  1968.                     }
  1969.                 }
  1970.             }
  1971.            
  1972.             return node;
  1973.         }
  1974.        
  1975.         /// <devdoc>
  1976.         /// Retrieves the head type description node for an instance.
  1977.         /// Instance-based node lists are rare. If a node list is not
  1978.         /// available for a given instance, this will return the head node
  1979.         /// for the instance's type.
  1980.         /// </devdoc>
  1981.         private static TypeDescriptionNode NodeFor(object instance)
  1982.         {
  1983.             return NodeFor(instance, false);
  1984.         }
  1985.        
  1986.         /// <devdoc>
  1987.         /// Retrieves the head type description node for an instance.
  1988.         /// Instance-based node lists are rare. If a node list is not
  1989.         /// available for a given instance, this will return the head node
  1990.         /// for the instance's type. This variation offers a bool called
  1991.         /// createDelegator. If true and there is no node list for this
  1992.         /// instance, NodeFor will create a temporary "delegator node" that,
  1993.         /// when queried, will delegate to the type stored in the instance.
  1994.         /// This is done on demand, which means if someone else added a
  1995.         /// type description provider for the instance's type the delegator
  1996.         /// would pick up the new type. If a query is being made that does
  1997.         /// not involve publicly exposing the type description provider for
  1998.         /// the instance, the query should pass in fase (the default) for
  1999.         /// createDelegator because no object will be created.
  2000.         /// </devdoc>
  2001.         private static TypeDescriptionNode NodeFor(object instance, bool createDelegator)
  2002.         {
  2003.             // For object instances, the provider cache key is not the object (that
  2004.             // would keep it in memory). Instead, it is a subclass of WeakReference
  2005.             // that overrides GetHashCode and Equals to make it appear to be the
  2006.             // object it is wrapping. A GC'd object causes WeakReference to return
  2007.             // false for all .Equals, but it always returns a valid hash code.
  2008.            
  2009.             Debug.Assert(instance != null, "Caller should validate");
  2010.            
  2011.             TypeDescriptionNode node = (TypeDescriptionNode)_providerTable[instance];
  2012.             if (node == null) {
  2013.                 Type type = instance.GetType();
  2014.                
  2015.                 if (type.IsCOMObject) {
  2016.                     type = ComObjectType;
  2017.                 }
  2018.                
  2019.                 if (createDelegator) {
  2020.                     node = new TypeDescriptionNode(new DelegatingTypeDescriptionProvider(type));
  2021.                     Trace("Nodes : Allocated new instance node for {0}. Now {1} nodes", type.Name, _providerTable.Count);
  2022.                 }
  2023.                 else {
  2024.                     node = NodeFor(type);
  2025.                 }
  2026.             }
  2027.            
  2028.             return node;
  2029.         }
  2030.        
  2031.         /// <devdoc>
  2032.         /// Simple linked list code to remove an element
  2033.         /// from the list. Returns the new head to the
  2034.         /// list. If the head points to an instance of
  2035.         /// DelegatingTypeDescriptionProvider, we clear the
  2036.         /// node because all it is doing is delegating elsewhere.
  2037.         ///
  2038.         /// Note that this behaves a little differently from normal
  2039.         /// linked list code. In a normal linked list, you remove
  2040.         /// then target node and fixup the links. In this linked
  2041.         /// list, we remove the node AFTER the target node, fixup
  2042.         /// the links, and fixup the underlying providers that each
  2043.         /// node references. The reason for this is that most
  2044.         /// providers keep a reference to the previous provider,
  2045.         /// which is exposed as one of these nodes. Therefore,
  2046.         /// to remove a provider the node following is most likely
  2047.         /// referenced by that provider
  2048.         /// </devdoc>
  2049.         private static void NodeRemove(object key, TypeDescriptionProvider provider)
  2050.         {
  2051.             lock (_providerTable) {
  2052.                 TypeDescriptionNode head = (TypeDescriptionNode)_providerTable[key];
  2053.                 TypeDescriptionNode target = head;
  2054.                 TypeDescriptionNode prev = null;
  2055.                
  2056.                 while (target != null && target.Provider != provider) {
  2057.                     prev = target;
  2058.                     target = target.Next;
  2059.                 }
  2060.                
  2061.                 if (target != null) {
  2062.                    
  2063.                     if (target.Next != null) {
  2064.                         // If there is a node after the target node,
  2065.                         // steal the node's provider and store it
  2066.                         // at the target location. This removes
  2067.                         // the provider at the target location without
  2068.                         // the need to modify providers which may be
  2069.                         // pointing to "target".
  2070.                         target.Provider = target.Next.Provider;
  2071.                        
  2072.                         // Now remove target.Next from the list
  2073.                         target.Next = target.Next.Next;
  2074.                        
  2075.                         // If the new provider we got is a delegating
  2076.                         // provider, we can remove this node from
  2077.                         // the list. The delegating provider should
  2078.                         // always be at the end of the node list.
  2079.                         if (target == head && target.Provider is DelegatingTypeDescriptionProvider) {
  2080.                             Debug.Assert(target.Next == null, "Delegating provider should always be the last provider in the chain.");
  2081.                             _providerTable.Remove(key);
  2082.                         }
  2083.                     }
  2084.                     else if (target != head) {
  2085.                         // If target is the last node, we can't
  2086.                         // assign a new provider over to it. What
  2087.                         // we can do, however, is assign a delegating
  2088.                         // provider into the target node. This routes
  2089.                         // requests from the previous provider into
  2090.                         // the next base type provider list.
  2091.                        
  2092.                         // We don't do this if the target is the head.
  2093.                         // In that case, we can remove the node
  2094.                         // altogether since no one is pointing to it.
  2095.                        
  2096.                         Type keyType = key as Type;
  2097.                         if (keyType == null)
  2098.                             keyType = key.GetType();
  2099.                        
  2100.                         target.Provider = new DelegatingTypeDescriptionProvider(keyType.BaseType);
  2101.                     }
  2102.                     else {
  2103.                         _providerTable.Remove(key);
  2104.                     }
  2105.                    
  2106.                     // Finally, clear our cache of provider types; it might be invalid
  2107.                     // now.
  2108.                     _providerTypeTable.Clear();
  2109.                 }
  2110.             }
  2111.         }
  2112.        
  2113.         /// <devdoc>
  2114.         /// This is the last stage in our filtering pipeline. Here, we apply any
  2115.         /// user-defined filter.
  2116.         /// </devdoc>
  2117.         private static ICollection PipelineAttributeFilter(int pipelineType, ICollection members, Attribute[] filter, object instance, IDictionary cache)
  2118.         {
  2119.             Debug.Assert(pipelineType != PIPELINE_ATTRIBUTES, "PipelineAttributeFilter is not supported for attributes");
  2120.            
  2121.             IList list = members as ArrayList;
  2122.            
  2123.             if (filter == null || filter.Length == 0) {
  2124.                 return members;
  2125.             }
  2126.            
  2127.             // Now, check our cache. The cache state is only valid
  2128.             // if the data coming into us is read-only. If it is read-write,
  2129.             // that means something higher in the pipeline has already changed
  2130.             // it so we must recompute anyway.
  2131.             //
  2132.             if (cache != null && (list == null || list.IsReadOnly)) {
  2133.                 AttributeFilterCacheItem filterCache = cache[_pipelineAttributeFilterKeys[pipelineType]] as AttributeFilterCacheItem;
  2134.                 if (filterCache != null && filterCache.IsValid(filter)) {
  2135.                     return filterCache.FilteredMembers;
  2136.                 }
  2137.             }
  2138.            
  2139.             // Our cache did not contain the correct state, so generate it.
  2140.             //
  2141.             if (list == null || list.IsReadOnly) {
  2142.                 Trace("Pipeline : Filter needs to create member list for {0}", instance.GetType().Name);
  2143.                 list = new ArrayList(members);
  2144.             }
  2145.            
  2146.             ArrayList filterResult = FilterMembers(list, filter);
  2147.             if (filterResult != null)
  2148.                 list = filterResult;
  2149.            
  2150.             // And, if we have a cache, store the updated state into it for future reference.
  2151.             //
  2152.             if (cache != null) {
  2153.                 ICollection cacheValue;
  2154.                
  2155.                 switch (pipelineType) {
  2156.                     case PIPELINE_PROPERTIES:
  2157.                         PropertyDescriptor[] propArray = new PropertyDescriptor[list.Count];
  2158.                         list.CopyTo(propArray, 0);
  2159.                         cacheValue = new PropertyDescriptorCollection(propArray, true);
  2160.                         break;
  2161.                     case PIPELINE_EVENTS:
  2162.                        
  2163.                         EventDescriptor[] eventArray = new EventDescriptor[list.Count];
  2164.                         list.CopyTo(eventArray, 0);
  2165.                         cacheValue = new EventDescriptorCollection(eventArray, true);
  2166.                         break;
  2167.                     default:
  2168.                        
  2169.                         Debug.Fail("unknown pipeline type");
  2170.                         cacheValue = null;
  2171.                         break;
  2172.                 }
  2173.                
  2174.                 Trace("Pipeline : Attribute Filter results being cached for {0}", instance.GetType().Name);
  2175.                 AttributeFilterCacheItem filterCache = new AttributeFilterCacheItem(filter, cacheValue);
  2176.                 cache[_pipelineAttributeFilterKeys[pipelineType]] = filterCache;
  2177.             }
  2178.            
  2179.             return list;
  2180.         }
  2181.        
  2182.         /// <devdoc>
  2183.         /// Metdata filtering is the third stage of our pipeline.
  2184.         /// In this stage we check to see if the given object is a
  2185.         /// sited component that provides the ITypeDescriptorFilterService
  2186.         /// object. If it does, we allow the TDS to filter the metadata.
  2187.         /// This will use the cache, if available, to store filtered
  2188.         /// metdata.
  2189.         /// </devdoc>
  2190.         private static ICollection PipelineFilter(int pipelineType, ICollection members, object instance, IDictionary cache)
  2191.         {
  2192.             IComponent component = instance as IComponent;
  2193.             ITypeDescriptorFilterService componentFilter = null;
  2194.            
  2195.             if (component != null) {
  2196.                 ISite site = component.Site;
  2197.                 if (site != null) {
  2198.                     componentFilter = site.GetService(typeof(ITypeDescriptorFilterService)) as ITypeDescriptorFilterService;
  2199.                 }
  2200.             }
  2201.            
  2202.             // If we have no filter, there is nothing for us to do.
  2203.             //
  2204.             IList list = members as ArrayList;
  2205.            
  2206.             if (componentFilter == null) {
  2207.                 Debug.Assert(cache == null || list == null || !cache.Contains(_pipelineFilterKeys[pipelineType]), "Earlier pipeline stage should have removed our cache");
  2208.                 return members;
  2209.             }
  2210.            
  2211.             // Now, check our cache. The cache state is only valid
  2212.             // if the data coming into us is read-only. If it is read-write,
  2213.             // that means something higher in the pipeline has already changed
  2214.             // it so we must recompute anyway.
  2215.             //
  2216.             if (cache != null && (list == null || list.IsReadOnly)) {
  2217.                 FilterCacheItem cacheItem = cache[_pipelineFilterKeys[pipelineType]] as FilterCacheItem;
  2218.                 if (cacheItem != null && cacheItem.IsValid(componentFilter)) {
  2219.                     return cacheItem.FilteredMembers;
  2220.                 }
  2221.             }
  2222.            
  2223.             // Cache either is dirty or doesn't exist. Re-filter the members.
  2224.             // We need to build an IDictionary of key->value pairs and invoke
  2225.             // Filter* on the filter service.
  2226.             //
  2227.             Hashtable filterTable = new Hashtable(members.Count);
  2228.             bool cacheResults;
  2229.            
  2230.             switch (pipelineType) {
  2231.                 case PIPELINE_ATTRIBUTES:
  2232.                     foreach (Attribute attr in members) {
  2233.                         filterTable[attr.TypeId] = attr;
  2234.                     }
  2235.                     cacheResults = componentFilter.FilterAttributes(component, filterTable);
  2236.                     break;
  2237.                 case PIPELINE_PROPERTIES:
  2238.                 case PIPELINE_EVENTS:
  2239.                    
  2240.                     foreach (MemberDescriptor desc in members) {
  2241.                         string descName = desc.Name;
  2242.                         // We must handle the case of duplicate property names
  2243.                         // because extender providers can provide any arbitrary
  2244.                         // name. Our rule for this is simple: If we find a
  2245.                         // duplicate name, resolve it back to the extender
  2246.                         // provider that offered it and append "_" + the
  2247.                         // provider name. If the provider has no name,
  2248.                         // then append the object hash code.
  2249.                         //
  2250.                         if (filterTable.Contains(descName)) {
  2251.                             // First, handle the new property. Because
  2252.                             // of the order in which we added extended
  2253.                             // properties earlier in the pipeline, we can be
  2254.                             // sure that the new property is an extender. We
  2255.                             // cannot be sure that the existing property
  2256.                             // in the table is an extender, so we will
  2257.                             // have to check.
  2258.                             //
  2259.                             string suffix = GetExtenderCollisionSuffix(desc);
  2260.                             Debug.Assert(suffix != null, "Name collision with non-extender property.");
  2261.                             if (suffix != null) {
  2262.                                 filterTable[descName + suffix] = desc;
  2263.                             }
  2264.                            
  2265.                             // Now, handle the original property.
  2266.                             //
  2267.                             MemberDescriptor origDesc = (MemberDescriptor)filterTable[descName];
  2268.                             suffix = GetExtenderCollisionSuffix(origDesc);
  2269.                             if (suffix != null) {
  2270.                                 filterTable.Remove(descName);
  2271.                                 filterTable[origDesc.Name + suffix] = origDesc;
  2272.                             }
  2273.                         }
  2274.                         else {
  2275.                             filterTable[descName] = desc;
  2276.                         }
  2277.                     }
  2278.                     if (pipelineType == PIPELINE_PROPERTIES) {
  2279.                         cacheResults = componentFilter.FilterProperties(component, filterTable);
  2280.                     }
  2281.                     else {
  2282.                         cacheResults = componentFilter.FilterEvents(component, filterTable);
  2283.                     }
  2284.                     break;
  2285.                 default:
  2286.                    
  2287.                     Debug.Fail("unknown pipeline type");
  2288.                     cacheResults = false;
  2289.                     break;
  2290.             }
  2291.            
  2292.             // See if we can re-use the IList were were passed. If we can,
  2293.             // it is more efficient to re-use its slots than to generate new ones.
  2294.             //
  2295.             if (list == null || list.IsReadOnly) {
  2296.                 Trace("Pipeline : Filter needs to create member list for {0}", instance.GetType().Name);
  2297.                 list = new ArrayList(filterTable.Values);
  2298.             }
  2299.             else {
  2300.                 list.Clear();
  2301.                 foreach (object obj in filterTable.Values) {
  2302.                     list.Add(obj);
  2303.                 }
  2304.             }
  2305.            
  2306.             // Component filter has requested that we cache these
  2307.             // new changes. We store them as a correctly typed collection
  2308.             // so on successive invocations we can simply return. Note that
  2309.             // we always return the IList so that successive stages in the
  2310.             // pipeline can modify it.
  2311.             //
  2312.             if (cacheResults && cache != null) {
  2313.                 ICollection cacheValue;
  2314.                
  2315.                 switch (pipelineType) {
  2316.                     case PIPELINE_ATTRIBUTES:
  2317.                         Attribute[] attrArray = new Attribute[list.Count];
  2318.                         try {
  2319.                             list.CopyTo(attrArray, 0);
  2320.                         }
  2321.                         catch (InvalidCastException) {
  2322.                             throw new ArgumentException(SR.GetString(SR.TypeDescriptorExpectedElementType, typeof(Attribute).FullName));
  2323.                         }
  2324.                         cacheValue = new AttributeCollection(attrArray);
  2325.                         break;
  2326.                     case PIPELINE_PROPERTIES:
  2327.                        
  2328.                         PropertyDescriptor[] propArray = new PropertyDescriptor[list.Count];
  2329.                         try {
  2330.                             list.CopyTo(propArray, 0);
  2331.                         }
  2332.                         catch (InvalidCastException) {
  2333.                             throw new ArgumentException(SR.GetString(SR.TypeDescriptorExpectedElementType, typeof(PropertyDescriptor).FullName));
  2334.                         }
  2335.                         cacheValue = new PropertyDescriptorCollection(propArray, true);
  2336.                         break;
  2337.                     case PIPELINE_EVENTS:
  2338.                        
  2339.                         EventDescriptor[] eventArray = new EventDescriptor[list.Count];
  2340.                         try {
  2341.                             list.CopyTo(eventArray, 0);
  2342.                         }
  2343.                         catch (InvalidCastException) {
  2344.                             throw new ArgumentException(SR.GetString(SR.TypeDescriptorExpectedElementType, typeof(EventDescriptor).FullName));
  2345.                         }
  2346.                         cacheValue = new EventDescriptorCollection(eventArray, true);
  2347.                         break;
  2348.                     default:
  2349.                        
  2350.                         Debug.Fail("unknown pipeline type");
  2351.                         cacheValue = null;
  2352.                         break;
  2353.                 }
  2354.                
  2355.                 Trace("Pipeline : Filter results being cached for {0}", instance.GetType().Name);
  2356.                
  2357.                 FilterCacheItem cacheItem = new FilterCacheItem(componentFilter, cacheValue);
  2358.                 cache[_pipelineFilterKeys[pipelineType]] = cacheItem;
  2359.                 cache.Remove(_pipelineAttributeFilterKeys[pipelineType]);
  2360.             }
  2361.            
  2362.             return list;
  2363.         }
  2364.        
  2365.         /// <devdoc>
  2366.         /// This is the first stage in the pipeline. This checks the incoming member collection and if it
  2367.         /// differs from what we have seen in the past, it invalidates all successive pipelines.
  2368.         /// </devdoc>
  2369.         private static ICollection PipelineInitialize(int pipelineType, ICollection members, IDictionary cache)
  2370.         {
  2371.             if (cache != null) {
  2372.                
  2373.                 bool cacheValid = true;
  2374.                
  2375.                 ICollection cachedMembers = cache[_pipelineInitializeKeys[pipelineType]] as ICollection;
  2376.                 if (cachedMembers != null && cachedMembers.Count == members.Count) {
  2377.                     IEnumerator cacheEnum = cachedMembers.GetEnumerator();
  2378.                     IEnumerator memberEnum = members.GetEnumerator();
  2379.                    
  2380.                     while (cacheEnum.MoveNext() && memberEnum.MoveNext()) {
  2381.                         if (cacheEnum.Current != memberEnum.Current) {
  2382.                             cacheValid = false;
  2383.                             break;
  2384.                         }
  2385.                     }
  2386.                 }
  2387.                
  2388.                 if (!cacheValid) {
  2389.                     // The cache wasn't valid. Remove all subsequent cache layers
  2390.                     // and then save off new data.
  2391.                     cache.Remove(_pipelineMergeKeys[pipelineType]);
  2392.                     cache.Remove(_pipelineFilterKeys[pipelineType]);
  2393.                     cache.Remove(_pipelineAttributeFilterKeys[pipelineType]);
  2394.                     cache[_pipelineInitializeKeys[pipelineType]] = members;
  2395.                 }
  2396.             }
  2397.            
  2398.             return members;
  2399.         }
  2400.        
  2401.         /// <devdoc>
  2402.         /// Metadata merging is the second stage of our metadata pipeline. This stage
  2403.         /// merges extended metdata with primary metadata, and stores it in
  2404.         /// the cache if it is available.
  2405.         /// </devdoc>
  2406.         private static ICollection PipelineMerge(int pipelineType, ICollection primary, ICollection secondary, object instance, IDictionary cache)
  2407.         {
  2408.             // If there is no secondary collection, there is nothing to merge.
  2409.             //
  2410.             if (secondary == null || secondary.Count == 0) {
  2411.                 return primary;
  2412.             }
  2413.            
  2414.             // Next, if we were given a cache, see if it has accurate data.
  2415.             //
  2416.             if (cache != null) {
  2417.                 ICollection mergeCache = cache[_pipelineMergeKeys[pipelineType]] as ICollection;
  2418.                 if (mergeCache != null && mergeCache.Count == (primary.Count + secondary.Count)) {
  2419.                     // Walk the merge cache.
  2420.                     IEnumerator mergeEnum = mergeCache.GetEnumerator();
  2421.                     IEnumerator primaryEnum = primary.GetEnumerator();
  2422.                     bool match = true;
  2423.                    
  2424.                     while (primaryEnum.MoveNext() && mergeEnum.MoveNext()) {
  2425.                         if (primaryEnum.Current != mergeEnum.Current) {
  2426.                             match = false;
  2427.                             break;
  2428.                         }
  2429.                     }
  2430.                    
  2431.                     if (match) {
  2432.                         IEnumerator secondaryEnum = secondary.GetEnumerator();
  2433.                        
  2434.                         while (secondaryEnum.MoveNext() && mergeEnum.MoveNext()) {
  2435.                             if (secondaryEnum.Current != mergeEnum.Current) {
  2436.                                 match = false;
  2437.                                 break;
  2438.                             }
  2439.                         }
  2440.                     }
  2441.                    
  2442.                     if (match) {
  2443.                         return mergeCache;
  2444.                     }
  2445.                 }
  2446.             }
  2447.            
  2448.             // Our cache didn't match. We need to merge metadata and return
  2449.             // the merged copy. We create an array list here, rather than
  2450.             // an array, because we want successive sections of the
  2451.             // pipeline to be able to modify it.
  2452.             //
  2453.             ArrayList list = new ArrayList(primary.Count + secondary.Count);
  2454.             foreach (object obj in primary) {
  2455.                 list.Add(obj);
  2456.             }
  2457.             foreach (object obj in secondary) {
  2458.                 list.Add(obj);
  2459.             }
  2460.            
  2461.             if (cache != null) {
  2462.                 ICollection cacheValue;
  2463.                
  2464.                 switch (pipelineType) {
  2465.                     case PIPELINE_ATTRIBUTES:
  2466.                         Attribute[] attrArray = new Attribute[list.Count];
  2467.                         list.CopyTo(attrArray, 0);
  2468.                         cacheValue = new AttributeCollection(attrArray);
  2469.                         break;
  2470.                     case PIPELINE_PROPERTIES:
  2471.                        
  2472.                         PropertyDescriptor[] propArray = new PropertyDescriptor[list.Count];
  2473.                         list.CopyTo(propArray, 0);
  2474.                         cacheValue = new PropertyDescriptorCollection(propArray, true);
  2475.                         break;
  2476.                     case PIPELINE_EVENTS:
  2477.                        
  2478.                         EventDescriptor[] eventArray = new EventDescriptor[list.Count];
  2479.                         list.CopyTo(eventArray, 0);
  2480.                         cacheValue = new EventDescriptorCollection(eventArray, true);
  2481.                         break;
  2482.                     default:
  2483.                        
  2484.                         Debug.Fail("unknown pipeline type");
  2485.                         cacheValue = null;
  2486.                         break;
  2487.                 }
  2488.                
  2489.                 Trace("Pipeline : Merge results being cached for {0}", instance.GetType().Name);
  2490.                 cache[_pipelineMergeKeys[pipelineType]] = cacheValue;
  2491.                 cache.Remove(_pipelineFilterKeys[pipelineType]);
  2492.                 cache.Remove(_pipelineAttributeFilterKeys[pipelineType]);
  2493.             }
  2494.            
  2495.             return list;
  2496.         }
  2497.        
  2498.         private static void RaiseRefresh(object component)
  2499.         {
  2500.             RefreshEventHandler handler = _refreshHandler;
  2501.            
  2502.             if (handler != null) {
  2503.                 handler(new RefreshEventArgs(component));
  2504.             }
  2505.         }
  2506.        
  2507.         private static void RaiseRefresh(Type type)
  2508.         {
  2509.             RefreshEventHandler handler = _refreshHandler;
  2510.            
  2511.             if (handler != null) {
  2512.                 handler(new RefreshEventArgs(type));
  2513.             }
  2514.         }
  2515.        
  2516.         /// <devdoc>
  2517.         /// Clears the properties and events for the specified
  2518.         /// component from the cache.
  2519.         /// </devdoc>
  2520.         public static void Refresh(object component)
  2521.         {
  2522.             #if DEBUG
  2523.             DebugTypeDescriptor.Refresh(component);
  2524.             #endif
  2525.            
  2526.             if (component == null) {
  2527.                 Debug.Fail("COMPAT: Returning, but you should not pass null here");
  2528.                 return;
  2529.             }
  2530.            
  2531.             // Build up a list of type description providers for
  2532.             // each type that is a derived type of the given
  2533.             // object. We will invalidate the metadata at
  2534.             // each of these levels.
  2535.            
  2536.             Type type = component.GetType();
  2537.             bool found = false;
  2538.            
  2539.             lock (_providerTable) {
  2540.                 // ReflectTypeDescritionProvider is only bound to object, but we
  2541.                 // need go to through the entire table to try to find custom
  2542.                 // providers. If we find one, will clear our cache.
  2543.                 foreach (DictionaryEntry de in _providerTable) {
  2544.                     Type nodeType = de.Key as Type;
  2545.                     if (nodeType != null && type.IsAssignableFrom(nodeType) || nodeType == typeof(object)) {
  2546.                         TypeDescriptionNode node = (TypeDescriptionNode)de.Value;
  2547.                         while (node != null && !(node.Provider is ReflectTypeDescriptionProvider)) {
  2548.                             found = true;
  2549.                             node = node.Next;
  2550.                         }
  2551.                        
  2552.                         if (node != null) {
  2553.                             ReflectTypeDescriptionProvider provider = (ReflectTypeDescriptionProvider)node.Provider;
  2554.                             if (provider.IsPopulated(type)) {
  2555.                                 found = true;
  2556.                                 provider.Refresh(type);
  2557.                             }
  2558.                         }
  2559.                     }
  2560.                 }
  2561.             }
  2562.            
  2563.             // We need to clear our filter even if no typedescriptionprovider had data.
  2564.             // This is because if you call Refresh(instance1) and Refresh(instance2)
  2565.             // and instance1 and instance2 are of the same type, you will end up not
  2566.             // actually deleting the dictionary cache on instance2 if you skip this
  2567.             // when you don't find a typedescriptionprovider.
  2568.             // However, we do not need to fire the event if we did not find any loaded
  2569.             // typedescriptionprovider AND the cache is empty (if someone repeatedly calls
  2570.             // Refresh on an instance).
  2571.            
  2572.             // Now, clear any cached data for the instance.
  2573.             //
  2574.             IDictionary cache = GetCache(component);
  2575.             if (found || cache != null) {
  2576.                 if (cache != null) {
  2577.                     Trace("Pipeline : Refresh clearing all pipeline caches");
  2578.                     for (int idx = 0; idx < _pipelineFilterKeys.Length; idx++) {
  2579.                         cache.Remove(_pipelineFilterKeys[idx]);
  2580.                         cache.Remove(_pipelineMergeKeys[idx]);
  2581.                         cache.Remove(_pipelineAttributeFilterKeys[idx]);
  2582.                     }
  2583.                    
  2584.                 }
  2585.                
  2586.                 Interlocked.Increment(ref _metadataVersion);
  2587.                
  2588.                 // And raise the event.
  2589.                 //
  2590.                 RaiseRefresh(component);
  2591.             }
  2592.         }
  2593.        
  2594.         /// <devdoc>
  2595.         /// Clears the properties and events for the specified type
  2596.         /// of component from the cache.
  2597.         /// </devdoc>
  2598.         public static void Refresh(Type type)
  2599.         {
  2600.             #if DEBUG
  2601.             DebugTypeDescriptor.Refresh(type);
  2602.             #endif
  2603.            
  2604.             if (type == null) {
  2605.                 Debug.Fail("COMPAT: Returning, but you should not pass null here");
  2606.                 return;
  2607.             }
  2608.            
  2609.             // Build up a list of type description providers for
  2610.             // each type that is a derived type of the given
  2611.             // type. We will invalidate the metadata at
  2612.             // each of these levels.
  2613.            
  2614.             bool found = false;
  2615.            
  2616.             lock (_providerTable) {
  2617.                 // ReflectTypeDescritionProvider is only bound to object, but we
  2618.                 // need go to through the entire table to try to find custom
  2619.                 // providers. If we find one, will clear our cache.
  2620.                 foreach (DictionaryEntry de in _providerTable) {
  2621.                     Type nodeType = de.Key as Type;
  2622.                     if (nodeType != null && type.IsAssignableFrom(nodeType) || nodeType == typeof(object)) {
  2623.                         TypeDescriptionNode node = (TypeDescriptionNode)de.Value;
  2624.                         while (node != null && !(node.Provider is ReflectTypeDescriptionProvider)) {
  2625.                             found = true;
  2626.                             node = node.Next;
  2627.                         }
  2628.                        
  2629.                         if (node != null) {
  2630.                             ReflectTypeDescriptionProvider provider = (ReflectTypeDescriptionProvider)node.Provider;
  2631.                             if (provider.IsPopulated(type)) {
  2632.                                 found = true;
  2633.                                 provider.Refresh(type);
  2634.                             }
  2635.                         }
  2636.                     }
  2637.                 }
  2638.             }
  2639.            
  2640.             // We only clear our filter and fire the refresh event if there was one or
  2641.             // more type description providers that were populated with metdata.
  2642.             // This prevents us from doing a lot of extra work and raising
  2643.             // a ton more events than we need to.
  2644.             //
  2645.             if (found) {
  2646.                 Interlocked.Increment(ref _metadataVersion);
  2647.                
  2648.                 // And raise the event.
  2649.                 //
  2650.                 RaiseRefresh(type);
  2651.             }
  2652.         }
  2653.        
  2654.         /// <devdoc>
  2655.         /// Clears the properties and events for the specified
  2656.         /// module from the cache.
  2657.         /// </devdoc>
  2658.         public static void Refresh(Module module)
  2659.         {
  2660.             #if DEBUG
  2661.             DebugTypeDescriptor.Refresh(module);
  2662.             #endif
  2663.            
  2664.             if (module == null) {
  2665.                 Debug.Fail("COMPAT: Returning, but you should not pass null here");
  2666.                 return;
  2667.             }
  2668.            
  2669.             // Build up a list of type description providers for
  2670.             // each type that is a derived type of the given
  2671.             // object. We will invalidate the metadata at
  2672.             // each of these levels.
  2673.             Hashtable refreshedTypes = null;
  2674.            
  2675.             lock (_providerTable) {
  2676.                 foreach (DictionaryEntry de in _providerTable) {
  2677.                     Type nodeType = de.Key as Type;
  2678.                     if (nodeType != null && nodeType.Module.Equals(module) || nodeType == typeof(object)) {
  2679.                         TypeDescriptionNode node = (TypeDescriptionNode)de.Value;
  2680.                         while (node != null && !(node.Provider is ReflectTypeDescriptionProvider)) {
  2681.                             if (refreshedTypes == null) {
  2682.                                 refreshedTypes = new Hashtable();
  2683.                             }
  2684.                             refreshedTypes[nodeType] = nodeType;
  2685.                             node = node.Next;
  2686.                         }
  2687.                        
  2688.                         if (node != null) {
  2689.                             ReflectTypeDescriptionProvider provider = (ReflectTypeDescriptionProvider)node.Provider;
  2690.                             Type[] populatedTypes = provider.GetPopulatedTypes(module);
  2691.                            
  2692.                             foreach (Type populatedType in populatedTypes) {
  2693.                                 provider.Refresh(populatedType);
  2694.                                 if (refreshedTypes == null) {
  2695.                                     refreshedTypes = new Hashtable();
  2696.                                 }
  2697.                                 refreshedTypes[populatedType] = populatedType;
  2698.                             }
  2699.                         }
  2700.                     }
  2701.                 }
  2702.             }
  2703.            
  2704.             // And raise the event if types were refresh and handlers are attached.
  2705.             //
  2706.             if (refreshedTypes != null && _refreshHandler != null) {
  2707.                 foreach (Type t in refreshedTypes.Keys) {
  2708.                     RaiseRefresh(t);
  2709.                 }
  2710.             }
  2711.         }
  2712.        
  2713.         /// <devdoc>
  2714.         /// Clears the properties and events for the specified
  2715.         /// assembly from the cache.
  2716.         /// </devdoc>
  2717.         [ResourceExposure(ResourceScope.None)]
  2718.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.Machine | ResourceScope.Assembly)]
  2719.         public static void Refresh(Assembly assembly)
  2720.         {
  2721.             if (assembly == null) {
  2722.                 Debug.Fail("COMPAT: Returning, but you should not pass null here");
  2723.                 return;
  2724.             }
  2725.            
  2726.             foreach (Module mod in assembly.GetModules()) {
  2727.                 Refresh(mod);
  2728.             }
  2729.            
  2730.             // Debug type descriptor has the same code, so our call above will handle this.
  2731.         }
  2732.        
  2733.         /// <devdoc>
  2734.         /// The RemoveAssociation method removes an association with an object.
  2735.         /// </devdoc>
  2736.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  2737.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  2738.         public static void RemoveAssociation(object primary, object secondary)
  2739.         {
  2740.             if (primary == null) {
  2741.                 throw new ArgumentNullException("primary");
  2742.             }
  2743.            
  2744.             if (secondary == null) {
  2745.                 throw new ArgumentNullException("secondary");
  2746.             }
  2747.            
  2748.             Hashtable assocTable = _associationTable;
  2749.             if (assocTable != null) {
  2750.                 IList associations = (IList)assocTable[primary];
  2751.                 if (associations != null) {
  2752.                     lock (associations) {
  2753.                         for (int idx = associations.Count - 1; idx >= 0; idx--) {
  2754.                             // Look for an associated object that has a type that
  2755.                             // matches the given type.
  2756.                             //
  2757.                             WeakReference weakRef = (WeakReference)associations[idx];
  2758.                             object secondaryItem = weakRef.Target;
  2759.                             if (secondaryItem == null || secondaryItem == secondary) {
  2760.                                 associations.RemoveAt(idx);
  2761.                             }
  2762.                         }
  2763.                     }
  2764.                 }
  2765.             }
  2766.         }
  2767.        
  2768.         /// <devdoc>
  2769.         /// The RemoveAssociations method removes all associations for a primary object.
  2770.         /// </devdoc>
  2771.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  2772.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  2773.         public static void RemoveAssociations(object primary)
  2774.         {
  2775.             if (primary == null) {
  2776.                 throw new ArgumentNullException("primary");
  2777.             }
  2778.            
  2779.             Hashtable assocTable = _associationTable;
  2780.             if (assocTable != null) {
  2781.                 assocTable.Remove(primary);
  2782.             }
  2783.         }
  2784.        
  2785.         /// <devdoc>
  2786.         /// The RemoveProvider method removes a previously added type
  2787.         /// description provider. Removing a provider causes a Refresh
  2788.         /// event to be raised for the object or type the provider is
  2789.         /// associated with.
  2790.         /// </devdoc>
  2791.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  2792.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  2793.         public static void RemoveProvider(TypeDescriptionProvider provider, Type type)
  2794.         {
  2795.             if (provider == null) {
  2796.                 throw new ArgumentNullException("provider");
  2797.             }
  2798.            
  2799.             if (type == null) {
  2800.                 throw new ArgumentNullException("type");
  2801.             }
  2802.            
  2803.             // Walk the nodes until we find the right one, and then remove it.
  2804.             NodeRemove(type, provider);
  2805.             RaiseRefresh(type);
  2806.         }
  2807.        
  2808.         /// <devdoc>
  2809.         /// The RemoveProvider method removes a previously added type
  2810.         /// description provider. Removing a provider causes a Refresh
  2811.         /// event to be raised for the object or type the provider is
  2812.         /// associated with.
  2813.         /// </devdoc>
  2814.         [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
  2815.         [EditorBrowsable(EditorBrowsableState.Advanced)]
  2816.         public static void RemoveProvider(TypeDescriptionProvider provider, object instance)
  2817.         {
  2818.             if (provider == null) {
  2819.                 throw new ArgumentNullException("provider");
  2820.             }
  2821.            
  2822.             if (instance == null) {
  2823.                 throw new ArgumentNullException("instance");
  2824.             }
  2825.            
  2826.             // Walk the nodes until we find the right one, and then remove it.
  2827.             NodeRemove(instance, provider);
  2828.             RaiseRefresh(instance);
  2829.         }
  2830.        
  2831.         /// <devdoc>
  2832.         /// This function takes a member descriptor and an attribute and determines whether
  2833.         /// the member satisfies the particular attribute. This either means that the member
  2834.         /// contains the attribute or the member does not contain the attribute and the default
  2835.         /// for the attribute matches the passed in attribute.
  2836.         /// </devdoc>
  2837.         private static bool ShouldHideMember(MemberDescriptor member, Attribute attribute)
  2838.         {
  2839.             if (member == null || attribute == null) {
  2840.                 return true;
  2841.             }
  2842.            
  2843.             Attribute memberAttribute = member.Attributes[attribute.GetType()];
  2844.             if (memberAttribute == null) {
  2845.                 return !attribute.IsDefaultAttribute();
  2846.             }
  2847.             else {
  2848.                 return !(attribute.Match(memberAttribute));
  2849.             }
  2850.         }
  2851.        
  2852.         /// <devdoc>
  2853.         /// Sorts descriptors by name of the descriptor.
  2854.         /// </devdoc>
  2855.         public static void SortDescriptorArray(IList infos)
  2856.         {
  2857.             if (infos == null) {
  2858.                 throw new ArgumentNullException("infos");
  2859.             }
  2860.            
  2861.             ArrayList.Adapter(infos).Sort(MemberDescriptorComparer.Instance);
  2862.         }
  2863.        
  2864.         /// <devdoc>
  2865.         /// Internal tracing API for debugging type descriptor.
  2866.         /// </devdoc>
  2867.         [Conditional("DEBUG")]
  2868.         static internal void Trace(string message, params object[] args)
  2869.         {
  2870.             Debug.WriteLineIf(TraceDescriptor.Enabled, string.Format(CultureInfo.InvariantCulture, "TypeDescriptor : {0}", string.Format(CultureInfo.InvariantCulture, message, args)));
  2871.         }
  2872.        
  2873.         /// <devdoc>
  2874.         /// This is a type description provider that adds the given
  2875.         /// array of attributes to a class or instance, preserving the rest
  2876.         /// of the metadata in the process.
  2877.         /// </devdoc>
  2878.         private sealed class AttributeProvider : TypeDescriptionProvider
  2879.         {
  2880.             Attribute[] _attrs;
  2881.            
  2882.             /// <devdoc>
  2883.             /// Creates a new attribute provider.
  2884.             /// </devdoc>
  2885.             internal AttributeProvider(TypeDescriptionProvider existingProvider, params Attribute[] attrs) : base(existingProvider)
  2886.             {
  2887.                 _attrs = attrs;
  2888.             }
  2889.            
  2890.             /// <devdoc>
  2891.             /// Creates a custom type descriptor that replaces the attributes.
  2892.             /// </devdoc>
  2893.             public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
  2894.             {
  2895.                 return new AttributeTypeDescriptor(_attrs, base.GetTypeDescriptor(objectType, instance));
  2896.             }
  2897.            
  2898.             /// <devdoc>
  2899.             /// Our custom type descriptor.
  2900.             /// </devdoc>
  2901.             private class AttributeTypeDescriptor : CustomTypeDescriptor
  2902.             {
  2903.                 Attribute[] _attributeArray;
  2904.                
  2905.                 /// <devdoc>
  2906.                 /// Creates a new custom type descriptor that can merge
  2907.                 /// the provided set of attributes with the existing set.
  2908.                 /// </devdoc>
  2909.                 internal AttributeTypeDescriptor(Attribute[] attrs, ICustomTypeDescriptor parent) : base(parent)
  2910.                 {
  2911.                     _attributeArray = attrs;
  2912.                 }
  2913.                
  2914.                 /// <devdoc>
  2915.                 /// Retrieves the merged set of attributes. We do not cache
  2916.                 /// this because there is always the possibility that someone
  2917.                 /// changed our parent provider's metadata. TypeDescriptor
  2918.                 /// will cache this for us anyhow.
  2919.                 /// </devdoc>
  2920.                 public override AttributeCollection GetAttributes()
  2921.                 {
  2922.                     Attribute[] finalAttr = null;
  2923.                     AttributeCollection existing = base.GetAttributes();
  2924.                     Attribute[] newAttrs = _attributeArray;
  2925.                     Attribute[] newArray = new Attribute[existing.Count + newAttrs.Length];
  2926.                     int actualCount = existing.Count;
  2927.                     existing.CopyTo(newArray, 0);
  2928.                    
  2929.                     for (int idx = 0; idx < newAttrs.Length; idx++) {
  2930.                        
  2931.                         Debug.Assert(newAttrs[idx] != null, "_attributes contains a null member");
  2932.                        
  2933.                         // We must see if this attribute is already in the existing
  2934.                         // array. If it is, we replace it.
  2935.                         bool match = false;
  2936.                         for (int existingIdx = 0; existingIdx < existing.Count; existingIdx++) {
  2937.                             if (newArray[existingIdx].TypeId.Equals(newAttrs[idx].TypeId)) {
  2938.                                 match = true;
  2939.                                 newArray[existingIdx] = newAttrs[idx];
  2940.                                 break;
  2941.                             }
  2942.                         }
  2943.                        
  2944.                         if (!match) {
  2945.                             newArray[actualCount++] = newAttrs[idx];
  2946.                         }
  2947.                     }
  2948.                    
  2949.                     // Now, if we collapsed some attributes, create a new array.
  2950.                     //
  2951.                     if (actualCount < newArray.Length) {
  2952.                         finalAttr = new Attribute[actualCount];
  2953.                         Array.Copy(newArray, 0, finalAttr, 0, actualCount);
  2954.                     }
  2955.                     else {
  2956.                         finalAttr = newArray;
  2957.                     }
  2958.                    
  2959.                     return new AttributeCollection(finalAttr);
  2960.                 }
  2961.             }
  2962.         }
  2963.        
  2964.         /// <devdoc>
  2965.         /// This class is a type description provider that works with the IComNativeDescriptorHandler
  2966.         /// interface.
  2967.         /// </devdoc>
  2968.         private sealed class ComNativeDescriptionProvider : TypeDescriptionProvider
  2969.         {
  2970.             #pragma warning disable 618
  2971.             private IComNativeDescriptorHandler _handler;
  2972.            
  2973.             internal ComNativeDescriptionProvider(IComNativeDescriptorHandler handler)
  2974.             {
  2975.                 _handler = handler;
  2976.             }
  2977.            
  2978.             /// <devdoc>
  2979.             /// Returns the COM handler object.
  2980.             /// </devdoc>
  2981.             internal IComNativeDescriptorHandler Handler {
  2982.                 get { return _handler; }
  2983.                 set { _handler = value; }
  2984.             }
  2985.             #pragma warning restore 618
  2986.            
  2987.             /// <devdoc>
  2988.             /// Implements GetTypeDescriptor. This creates a custom type
  2989.             /// descriptor that walks the linked list for each of its calls.
  2990.             /// </devdoc>
  2991.            
  2992.             [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")]
  2993.             public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
  2994.             {
  2995.                 if (objectType == null) {
  2996.                     throw new ArgumentNullException("objectType");
  2997.                 }
  2998.                
  2999.                 if (instance == null) {
  3000.                     return null;
  3001.                 }
  3002.                
  3003.                 if (!objectType.IsInstanceOfType(instance)) {
  3004.                     throw new ArgumentException("instance");
  3005.                 }
  3006.                
  3007.                 return new ComNativeTypeDescriptor(_handler, instance);
  3008.             }
  3009.            
  3010.             /// <devdoc>
  3011.             /// This type descriptor sits on top of a native
  3012.             /// descriptor handler.
  3013.             /// </devdoc>
  3014.             private sealed class ComNativeTypeDescriptor : ICustomTypeDescriptor
  3015.             {
  3016.                 #pragma warning disable 618
  3017.                 private IComNativeDescriptorHandler _handler;
  3018.                 private object _instance;
  3019.                
  3020.                 /// <devdoc>
  3021.                 /// Creates a new ComNativeTypeDescriptor.
  3022.                 /// </devdoc>
  3023.                 internal ComNativeTypeDescriptor(IComNativeDescriptorHandler handler, object instance)
  3024.                 {
  3025.                     _handler = handler;
  3026.                     _instance = instance;
  3027.                 }
  3028.                 #pragma warning restore 618
  3029.                
  3030.                 /// <devdoc>
  3031.                 /// ICustomTypeDescriptor implementation.
  3032.                 /// </devdoc>
  3033.                 AttributeCollection ICustomTypeDescriptor.GetAttributes()
  3034.                 {
  3035.                     return _handler.GetAttributes(_instance);
  3036.                 }
  3037.                
  3038.                 /// <devdoc>
  3039.                 /// ICustomTypeDescriptor implementation.
  3040.                 /// </devdoc>
  3041.                 string ICustomTypeDescriptor.GetClassName()
  3042.                 {
  3043.                     return _handler.GetClassName(_instance);
  3044.                 }
  3045.                
  3046.                 /// <devdoc>
  3047.                 /// ICustomTypeDescriptor implementation.
  3048.                 /// </devdoc>
  3049.                 string ICustomTypeDescriptor.GetComponentName()
  3050.                 {
  3051.                     return null;
  3052.                 }
  3053.                
  3054.                 /// <devdoc>
  3055.                 /// ICustomTypeDescriptor implementation.
  3056.                 /// </devdoc>
  3057.                 TypeConverter ICustomTypeDescriptor.GetConverter()
  3058.                 {
  3059.                     return _handler.GetConverter(_instance);
  3060.                 }
  3061.                
  3062.                 /// <devdoc>
  3063.                 /// ICustomTypeDescriptor implementation.
  3064.                 /// </devdoc>
  3065.                 EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
  3066.                 {
  3067.                     return _handler.GetDefaultEvent(_instance);
  3068.                 }
  3069.                
  3070.                 /// <devdoc>
  3071.                 /// ICustomTypeDescriptor implementation.
  3072.                 /// </devdoc>
  3073.                 PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
  3074.                 {
  3075.                     return _handler.GetDefaultProperty(_instance);
  3076.                 }
  3077.                
  3078.                 /// <devdoc>
  3079.                 /// ICustomTypeDescriptor implementation.
  3080.                 /// </devdoc>
  3081.                 object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
  3082.                 {
  3083.                     return _handler.GetEditor(_instance, editorBaseType);
  3084.                 }
  3085.                
  3086.                 /// <devdoc>
  3087.                 /// ICustomTypeDescriptor implementation.
  3088.                 /// </devdoc>
  3089.                 EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
  3090.                 {
  3091.                     return _handler.GetEvents(_instance);
  3092.                 }
  3093.                
  3094.                 /// <devdoc>
  3095.                 /// ICustomTypeDescriptor implementation.
  3096.                 /// </devdoc>
  3097.                 EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
  3098.                 {
  3099.                     return _handler.GetEvents(_instance, attributes);
  3100.                 }
  3101.                
  3102.                 /// <devdoc>
  3103.                 /// ICustomTypeDescriptor implementation.
  3104.                 /// </devdoc>
  3105.                 PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
  3106.                 {
  3107.                     return _handler.GetProperties(_instance, null);
  3108.                 }
  3109.                
  3110.                 /// <devdoc>
  3111.                 /// ICustomTypeDescriptor implementation.
  3112.                 /// </devdoc>
  3113.                 PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
  3114.                 {
  3115.                     return _handler.GetProperties(_instance, attributes);
  3116.                 }
  3117.                
  3118.                 /// <devdoc>
  3119.                 /// ICustomTypeDescriptor implementation.
  3120.                 /// </devdoc>
  3121.                 object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
  3122.                 {
  3123.                     return _instance;
  3124.                 }
  3125.             }
  3126.         }
  3127.        
  3128.         /// <devdoc>
  3129.         /// This is a simple class that is used to store a filtered
  3130.         /// set of members in an object's dictionary cache. It is
  3131.         /// used by the PipelineAttributeFilter method.
  3132.         /// </devdoc>
  3133.         private sealed class AttributeFilterCacheItem
  3134.         {
  3135.             private Attribute[] _filter;
  3136.             internal ICollection FilteredMembers;
  3137.            
  3138.             internal AttributeFilterCacheItem(Attribute[] filter, ICollection filteredMembers)
  3139.             {
  3140.                 _filter = filter;
  3141.                 FilteredMembers = filteredMembers;
  3142.             }
  3143.            
  3144.             internal bool IsValid(Attribute[] filter)
  3145.             {
  3146.                 if (_filter.Length != filter.Length)
  3147.                     return false;
  3148.                
  3149.                 for (int idx = 0; idx < filter.Length; idx++) {
  3150.                     if (_filter[idx] != filter[idx]) {
  3151.                         return false;
  3152.                     }
  3153.                 }
  3154.                
  3155.                 return true;
  3156.             }
  3157.         }
  3158.        
  3159.         /// <devdoc>
  3160.         /// This small class contains cache information for the filter stage of our
  3161.         /// caching algorithm. It is used by the PipelineFilter method.
  3162.         /// </devdoc>
  3163.         private sealed class FilterCacheItem
  3164.         {
  3165.             private ITypeDescriptorFilterService _filterService;
  3166.             internal ICollection FilteredMembers;
  3167.            
  3168.             internal FilterCacheItem(ITypeDescriptorFilterService filterService, ICollection filteredMembers)
  3169.             {
  3170.                 _filterService = filterService;
  3171.                 FilteredMembers = filteredMembers;
  3172.             }
  3173.            
  3174.             internal bool IsValid(ITypeDescriptorFilterService filterService)
  3175.             {
  3176.                 if (!Object.ReferenceEquals(_filterService, filterService))
  3177.                     return false;
  3178.                 return true;
  3179.             }
  3180.         }
  3181.        
  3182.         /// <devdoc>
  3183.         /// An unimplemented interface. What is this? It is an interface that nobody ever
  3184.         /// implements, of course? Where and why would it be used? Why, to find cross-process
  3185.         /// remoted objects, of course! If a well-known object comes in from a cross process
  3186.         /// connection, the remoting layer does contain enough type information to determine
  3187.         /// if an object implements an interface. It assumes that if you are going to cast
  3188.         /// an object to an interface that you know what you're doing, and allows the cast,
  3189.         /// even for objects that DON'T actually implement the interface. The error here
  3190.         /// is raised later when you make your first call on that interface pointer: you
  3191.         /// get a remoting exception.
  3192.         ///
  3193.         /// This is a big problem for code that does "is" and "as" checks to detect the
  3194.         /// presence of an interface. We do that all over the place here, so we do a check
  3195.         /// during parameter validation to see if an object implements IUnimplemented. If it
  3196.         /// does, we know that what we really have is a lying remoting proxy, and we bail.
  3197.         /// </devdoc>
  3198.         private interface IUnimplemented
  3199.         {
  3200.         }
  3201.        
  3202.         /// <devdoc>
  3203.         /// This comparer compares member descriptors for sorting.
  3204.         /// </devdoc>
  3205.         private sealed class MemberDescriptorComparer : IComparer
  3206.         {
  3207.             public static readonly MemberDescriptorComparer Instance = new MemberDescriptorComparer();
  3208.            
  3209.             public int Compare(object left, object right)
  3210.             {
  3211.                 return string.Compare(((MemberDescriptor)left).Name, ((MemberDescriptor)right).Name, false, CultureInfo.InvariantCulture);
  3212.             }
  3213.         }
  3214.        
  3215.         /// <devdoc>
  3216.         /// This is a merged type descriptor that can merge the output of
  3217.         /// a primary and secondary type descriptor. If the primary doesn't
  3218.         /// provide the needed information, the request is passed on to the
  3219.         /// secondary.
  3220.         /// </devdoc>
  3221.         private sealed class MergedTypeDescriptor : ICustomTypeDescriptor
  3222.         {
  3223.             private ICustomTypeDescriptor _primary;
  3224.             private ICustomTypeDescriptor _secondary;
  3225.            
  3226.             /// <devdoc>
  3227.             /// Creates a new MergedTypeDescriptor.
  3228.             /// </devdoc>
  3229.             internal MergedTypeDescriptor(ICustomTypeDescriptor primary, ICustomTypeDescriptor secondary)
  3230.             {
  3231.                 _primary = primary;
  3232.                 _secondary = secondary;
  3233.             }
  3234.            
  3235.             /// <devdoc>
  3236.             /// ICustomTypeDescriptor implementation.
  3237.             /// </devdoc>
  3238.             AttributeCollection ICustomTypeDescriptor.GetAttributes()
  3239.             {
  3240.                 AttributeCollection attrs = _primary.GetAttributes();
  3241.                 if (attrs == null) {
  3242.                     attrs = _secondary.GetAttributes();
  3243.                 }
  3244.                
  3245.                 Debug.Assert(attrs != null, "Someone should have handled this");
  3246.                 return attrs;
  3247.             }
  3248.            
  3249.             /// <devdoc>
  3250.             /// ICustomTypeDescriptor implementation.
  3251.             /// </devdoc>
  3252.             string ICustomTypeDescriptor.GetClassName()
  3253.             {
  3254.                 string className = _primary.GetClassName();
  3255.                 if (className == null) {
  3256.                     className = _secondary.GetClassName();
  3257.                 }
  3258.                
  3259.                 Debug.Assert(className != null, "Someone should have handled this");
  3260.                 return className;
  3261.             }
  3262.            
  3263.             /// <devdoc>
  3264.             /// ICustomTypeDescriptor implementation.
  3265.             /// </devdoc>
  3266.             string ICustomTypeDescriptor.GetComponentName()
  3267.             {
  3268.                 string name = _primary.GetComponentName();
  3269.                 if (name == null) {
  3270.                     name = _secondary.GetComponentName();
  3271.                 }
  3272.                
  3273.                 return name;
  3274.             }
  3275.            
  3276.             /// <devdoc>
  3277.             /// ICustomTypeDescriptor implementation.
  3278.             /// </devdoc>
  3279.             TypeConverter ICustomTypeDescriptor.GetConverter()
  3280.             {
  3281.                 TypeConverter converter = _primary.GetConverter();
  3282.                 if (converter == null) {
  3283.                     converter = _secondary.GetConverter();
  3284.                 }
  3285.                
  3286.                 Debug.Assert(converter != null, "Someone should have handled this");
  3287.                 return converter;
  3288.             }
  3289.            
  3290.             /// <devdoc>
  3291.             /// ICustomTypeDescriptor implementation.
  3292.             /// </devdoc>
  3293.             EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
  3294.             {
  3295.                 EventDescriptor evt = _primary.GetDefaultEvent();
  3296.                 if (evt == null) {
  3297.                     evt = _secondary.GetDefaultEvent();
  3298.                 }
  3299.                
  3300.                 return evt;
  3301.             }
  3302.            
  3303.             /// <devdoc>
  3304.             /// ICustomTypeDescriptor implementation.
  3305.             /// </devdoc>
  3306.             PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
  3307.             {
  3308.                 PropertyDescriptor prop = _primary.GetDefaultProperty();
  3309.                 if (prop == null) {
  3310.                     prop = _secondary.GetDefaultProperty();
  3311.                 }
  3312.                
  3313.                 return prop;
  3314.             }
  3315.            
  3316.             /// <devdoc>
  3317.             /// ICustomTypeDescriptor implementation.
  3318.             /// </devdoc>
  3319.             object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
  3320.             {
  3321.                 if (editorBaseType == null) {
  3322.                     throw new ArgumentNullException("editorBaseType");
  3323.                 }
  3324.                
  3325.                 object editor = _primary.GetEditor(editorBaseType);
  3326.                 if (editor == null) {
  3327.                     editor = _secondary.GetEditor(editorBaseType);
  3328.                 }
  3329.                
  3330.                 return editor;
  3331.             }
  3332.            
  3333.             /// <devdoc>
  3334.             /// ICustomTypeDescriptor implementation.
  3335.             /// </devdoc>
  3336.             EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
  3337.             {
  3338.                 EventDescriptorCollection events = _primary.GetEvents();
  3339.                 if (events == null) {
  3340.                     events = _secondary.GetEvents();
  3341.                 }
  3342.                
  3343.                 Debug.Assert(events != null, "Someone should have handled this");
  3344.                 return events;
  3345.             }
  3346.            
  3347.             /// <devdoc>
  3348.             /// ICustomTypeDescriptor implementation.
  3349.             /// </devdoc>
  3350.             EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
  3351.             {
  3352.                 EventDescriptorCollection events = _primary.GetEvents(attributes);
  3353.                 if (events == null) {
  3354.                     events = _secondary.GetEvents(attributes);
  3355.                 }
  3356.                
  3357.                 Debug.Assert(events != null, "Someone should have handled this");
  3358.                 return events;
  3359.             }
  3360.            
  3361.             /// <devdoc>
  3362.             /// ICustomTypeDescriptor implementation.
  3363.             /// </devdoc>
  3364.             PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
  3365.             {
  3366.                 PropertyDescriptorCollection properties = _primary.GetProperties();
  3367.                 if (properties == null) {
  3368.                     properties = _secondary.GetProperties();
  3369.                 }
  3370.                
  3371.                 Debug.Assert(properties != null, "Someone should have handled this");
  3372.                 return properties;
  3373.             }
  3374.            
  3375.             /// <devdoc>
  3376.             /// ICustomTypeDescriptor implementation.
  3377.             /// </devdoc>
  3378.             PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
  3379.             {
  3380.                 PropertyDescriptorCollection properties = _primary.GetProperties(attributes);
  3381.                 if (properties == null) {
  3382.                     properties = _secondary.GetProperties(attributes);
  3383.                 }
  3384.                
  3385.                 Debug.Assert(properties != null, "Someone should have handled this");
  3386.                 return properties;
  3387.             }
  3388.            
  3389.             /// <devdoc>
  3390.             /// ICustomTypeDescriptor implementation.
  3391.             /// </devdoc>
  3392.             object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
  3393.             {
  3394.                 object owner = _primary.GetPropertyOwner(pd);
  3395.                 if (owner == null) {
  3396.                     owner = _secondary.GetPropertyOwner(pd);
  3397.                 }
  3398.                
  3399.                 return owner;
  3400.             }
  3401.         }
  3402.        
  3403.         /// <devdoc>
  3404.         /// This is a linked list node that is comprised of a type
  3405.         /// description provider. Each node contains a Next pointer
  3406.         /// to the next node in the list and also a Provider pointer
  3407.         /// which contains the type description provider this node
  3408.         /// represents. The implementation of TypeDescriptionProvider
  3409.         /// that the node provides simply invokes the corresponding
  3410.         /// method on the node's provider.
  3411.         /// </devdoc>
  3412.         private sealed class TypeDescriptionNode : TypeDescriptionProvider
  3413.         {
  3414.             internal TypeDescriptionNode Next;
  3415.             internal TypeDescriptionProvider Provider;
  3416.            
  3417.             /// <devdoc>
  3418.             /// Creates a new type description node.
  3419.             /// </devdoc>
  3420.             internal TypeDescriptionNode(TypeDescriptionProvider provider)
  3421.             {
  3422.                 Provider = provider;
  3423.             }
  3424.            
  3425.             /// <devdoc>
  3426.             /// Implements CreateInstance. This just walks the linked list
  3427.             /// looking for someone who implements the call.
  3428.             /// </devdoc>
  3429.             public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
  3430.             {
  3431.                 if (objectType == null) {
  3432.                     throw new ArgumentNullException("objectType");
  3433.                 }
  3434.                
  3435.                 if (argTypes != null) {
  3436.                     if (args == null) {
  3437.                         throw new ArgumentNullException("args");
  3438.                     }
  3439.                    
  3440.                     if (argTypes.Length != args.Length) {
  3441.                         throw new ArgumentException(SR.GetString(SR.TypeDescriptorArgsCountMismatch));
  3442.                     }
  3443.                 }
  3444.                
  3445.                 return Provider.CreateInstance(provider, objectType, argTypes, args);
  3446.             }
  3447.            
  3448.             /// <devdoc>
  3449.             /// Implements GetCache. This just walks the linked
  3450.             /// list looking for someone who implements the call.
  3451.             /// </devdoc>
  3452.             public override IDictionary GetCache(object instance)
  3453.             {
  3454.                 if (instance == null) {
  3455.                     throw new ArgumentNullException("instance");
  3456.                 }
  3457.                
  3458.                 return Provider.GetCache(instance);
  3459.             }
  3460.            
  3461.             /// <devdoc>
  3462.             /// Implements GetExtendedTypeDescriptor. This creates a custom type
  3463.             /// descriptor that walks the linked list for each of its calls.
  3464.             /// </devdoc>
  3465.             public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
  3466.             {
  3467.                 if (instance == null) {
  3468.                     throw new ArgumentNullException("instance");
  3469.                 }
  3470.                
  3471.                 return new DefaultExtendedTypeDescriptor(this, instance);
  3472.             }
  3473.            
  3474.             /// <devdoc>
  3475.             /// The name of the specified component, or null if the component has no name.
  3476.             /// In many cases this will return the same value as GetComponentName. If the
  3477.             /// component resides in a nested container or has other nested semantics, it may
  3478.             /// return a different fully qualfied name.
  3479.             ///
  3480.             /// If not overridden, the default implementation of this method will call
  3481.             /// GetTypeDescriptor.GetComponentName.
  3482.             /// </devdoc>
  3483.             public override string GetFullComponentName(object component)
  3484.             {
  3485.                 if (component == null) {
  3486.                     throw new ArgumentNullException("component");
  3487.                 }
  3488.                
  3489.                 return Provider.GetFullComponentName(component);
  3490.             }
  3491.            
  3492.             /// <devdoc>
  3493.             /// Implements GetReflectionType. This just walks the linked list
  3494.             /// looking for someone who implements the call.
  3495.             /// </devdoc>
  3496.             public override Type GetReflectionType(Type objectType, object instance)
  3497.             {
  3498.                 if (objectType == null) {
  3499.                     throw new ArgumentNullException("objectType");
  3500.                 }
  3501.                
  3502.                 return Provider.GetReflectionType(objectType, instance);
  3503.             }
  3504.            
  3505.             /// <devdoc>
  3506.             /// Implements GetTypeDescriptor. This creates a custom type
  3507.             /// descriptor that walks the linked list for each of its calls.
  3508.             /// </devdoc>
  3509.            
  3510.             [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")]
  3511.             public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
  3512.             {
  3513.                 if (objectType == null) {
  3514.                     throw new ArgumentNullException("objectType");
  3515.                 }
  3516.                
  3517.                 if (instance != null && !objectType.IsInstanceOfType(instance)) {
  3518.                     throw new ArgumentException("instance");
  3519.                 }
  3520.                
  3521.                 return new DefaultTypeDescriptor(this, objectType, instance);
  3522.             }
  3523.            
  3524.             /// <devdoc>
  3525.             /// A type descriptor for extended types. This type descriptor
  3526.             /// looks at the head node in the linked list.
  3527.             /// </devdoc>
  3528.             private struct DefaultExtendedTypeDescriptor : ICustomTypeDescriptor
  3529.             {
  3530.                 private TypeDescriptionNode _node;
  3531.                 private object _instance;
  3532.                
  3533.                 /// <devdoc>
  3534.                 /// Creates a new WalkingExtendedTypeDescriptor.
  3535.                 /// </devdoc>
  3536.                 internal DefaultExtendedTypeDescriptor(TypeDescriptionNode node, object instance)
  3537.                 {
  3538.                     _node = node;
  3539.                     _instance = instance;
  3540.                 }
  3541.                
  3542.                 /// <devdoc>
  3543.                 /// ICustomTypeDescriptor implementation.
  3544.                 /// </devdoc>
  3545.                 AttributeCollection ICustomTypeDescriptor.GetAttributes()
  3546.                 {
  3547.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3548.                     // If so, we can call on it directly rather than creating another
  3549.                     // custom type descriptor
  3550.                    
  3551.                     TypeDescriptionProvider p = _node.Provider;
  3552.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3553.                    
  3554.                     if (rp != null) {
  3555.                         return rp.GetExtendedAttributes(_instance);
  3556.                     }
  3557.                    
  3558.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3559.                     if (desc == null)
  3560.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3561.                     AttributeCollection attrs = desc.GetAttributes();
  3562.                     if (attrs == null)
  3563.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetAttributes"));
  3564.                     return attrs;
  3565.                 }
  3566.                
  3567.                 /// <devdoc>
  3568.                 /// ICustomTypeDescriptor implementation.
  3569.                 /// </devdoc>
  3570.                 string ICustomTypeDescriptor.GetClassName()
  3571.                 {
  3572.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3573.                     // If so, we can call on it directly rather than creating another
  3574.                     // custom type descriptor
  3575.                    
  3576.                     TypeDescriptionProvider p = _node.Provider;
  3577.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3578.                    
  3579.                     if (rp != null) {
  3580.                         return rp.GetExtendedClassName(_instance);
  3581.                     }
  3582.                    
  3583.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3584.                     if (desc == null)
  3585.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3586.                     string name = desc.GetClassName();
  3587.                     if (name == null)
  3588.                         name = _instance.GetType().FullName;
  3589.                     return name;
  3590.                 }
  3591.                
  3592.                 /// <devdoc>
  3593.                 /// ICustomTypeDescriptor implementation.
  3594.                 /// </devdoc>
  3595.                 string ICustomTypeDescriptor.GetComponentName()
  3596.                 {
  3597.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3598.                     // If so, we can call on it directly rather than creating another
  3599.                     // custom type descriptor
  3600.                    
  3601.                     TypeDescriptionProvider p = _node.Provider;
  3602.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3603.                    
  3604.                     if (rp != null) {
  3605.                         return rp.GetExtendedComponentName(_instance);
  3606.                     }
  3607.                    
  3608.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3609.                     if (desc == null)
  3610.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3611.                     return desc.GetComponentName();
  3612.                 }
  3613.                
  3614.                 /// <devdoc>
  3615.                 /// ICustomTypeDescriptor implementation.
  3616.                 /// </devdoc>
  3617.                 TypeConverter ICustomTypeDescriptor.GetConverter()
  3618.                 {
  3619.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3620.                     // If so, we can call on it directly rather than creating another
  3621.                     // custom type descriptor
  3622.                    
  3623.                     TypeDescriptionProvider p = _node.Provider;
  3624.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3625.                    
  3626.                     if (rp != null) {
  3627.                         return rp.GetExtendedConverter(_instance);
  3628.                     }
  3629.                    
  3630.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3631.                     if (desc == null)
  3632.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3633.                     TypeConverter converter = desc.GetConverter();
  3634.                     if (converter == null)
  3635.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetConverter"));
  3636.                     return converter;
  3637.                 }
  3638.                
  3639.                 /// <devdoc>
  3640.                 /// ICustomTypeDescriptor implementation.
  3641.                 /// </devdoc>
  3642.                 EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
  3643.                 {
  3644.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3645.                     // If so, we can call on it directly rather than creating another
  3646.                     // custom type descriptor
  3647.                    
  3648.                     TypeDescriptionProvider p = _node.Provider;
  3649.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3650.                    
  3651.                     if (rp != null) {
  3652.                         return rp.GetExtendedDefaultEvent(_instance);
  3653.                     }
  3654.                    
  3655.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3656.                     if (desc == null)
  3657.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3658.                     return desc.GetDefaultEvent();
  3659.                 }
  3660.                
  3661.                 /// <devdoc>
  3662.                 /// ICustomTypeDescriptor implementation.
  3663.                 /// </devdoc>
  3664.                 PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
  3665.                 {
  3666.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3667.                     // If so, we can call on it directly rather than creating another
  3668.                     // custom type descriptor
  3669.                    
  3670.                     TypeDescriptionProvider p = _node.Provider;
  3671.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3672.                    
  3673.                     if (rp != null) {
  3674.                         return rp.GetExtendedDefaultProperty(_instance);
  3675.                     }
  3676.                    
  3677.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3678.                     if (desc == null)
  3679.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3680.                     return desc.GetDefaultProperty();
  3681.                 }
  3682.                
  3683.                 /// <devdoc>
  3684.                 /// ICustomTypeDescriptor implementation.
  3685.                 /// </devdoc>
  3686.                 object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
  3687.                 {
  3688.                     if (editorBaseType == null) {
  3689.                         throw new ArgumentNullException("editorBaseType");
  3690.                     }
  3691.                    
  3692.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3693.                     // If so, we can call on it directly rather than creating another
  3694.                     // custom type descriptor
  3695.                    
  3696.                     TypeDescriptionProvider p = _node.Provider;
  3697.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3698.                    
  3699.                     if (rp != null) {
  3700.                         return rp.GetExtendedEditor(_instance, editorBaseType);
  3701.                     }
  3702.                    
  3703.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3704.                     if (desc == null)
  3705.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3706.                     return desc.GetEditor(editorBaseType);
  3707.                 }
  3708.                
  3709.                 /// <devdoc>
  3710.                 /// ICustomTypeDescriptor implementation.
  3711.                 /// </devdoc>
  3712.                 EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
  3713.                 {
  3714.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3715.                     // If so, we can call on it directly rather than creating another
  3716.                     // custom type descriptor
  3717.                    
  3718.                     TypeDescriptionProvider p = _node.Provider;
  3719.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3720.                    
  3721.                     if (rp != null) {
  3722.                         return rp.GetExtendedEvents(_instance);
  3723.                     }
  3724.                    
  3725.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3726.                     if (desc == null)
  3727.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3728.                     EventDescriptorCollection events = desc.GetEvents();
  3729.                     if (events == null)
  3730.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetEvents"));
  3731.                     return events;
  3732.                 }
  3733.                
  3734.                 /// <devdoc>
  3735.                 /// ICustomTypeDescriptor implementation.
  3736.                 /// </devdoc>
  3737.                 EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
  3738.                 {
  3739.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3740.                     // If so, we can call on it directly rather than creating another
  3741.                     // custom type descriptor
  3742.                    
  3743.                     TypeDescriptionProvider p = _node.Provider;
  3744.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3745.                    
  3746.                     if (rp != null) {
  3747.                         // There is no need to filter these events. For extended objects, they
  3748.                         // are accessed through our pipeline code, which always filters before
  3749.                         // returning. So any filter we do here is redundant. Note that we do
  3750.                         // pass a valid filter to a custom descriptor so it can optimize if it wants.
  3751.                         EventDescriptorCollection events = rp.GetExtendedEvents(_instance);
  3752.                         return events;
  3753.                     }
  3754.                    
  3755.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3756.                     if (desc == null)
  3757.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3758.                     EventDescriptorCollection evts = desc.GetEvents(attributes);
  3759.                     if (evts == null)
  3760.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetEvents"));
  3761.                     return evts;
  3762.                 }
  3763.                
  3764.                 /// <devdoc>
  3765.                 /// ICustomTypeDescriptor implementation.
  3766.                 /// </devdoc>
  3767.                 PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
  3768.                 {
  3769.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3770.                     // If so, we can call on it directly rather than creating another
  3771.                     // custom type descriptor
  3772.                    
  3773.                     TypeDescriptionProvider p = _node.Provider;
  3774.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3775.                    
  3776.                     if (rp != null) {
  3777.                         return rp.GetExtendedProperties(_instance);
  3778.                     }
  3779.                    
  3780.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3781.                     if (desc == null)
  3782.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3783.                     PropertyDescriptorCollection properties = desc.GetProperties();
  3784.                     if (properties == null)
  3785.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetProperties"));
  3786.                     return properties;
  3787.                 }
  3788.                
  3789.                 /// <devdoc>
  3790.                 /// ICustomTypeDescriptor implementation.
  3791.                 /// </devdoc>
  3792.                 PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
  3793.                 {
  3794.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3795.                     // If so, we can call on it directly rather than creating another
  3796.                     // custom type descriptor
  3797.                    
  3798.                     TypeDescriptionProvider p = _node.Provider;
  3799.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3800.                    
  3801.                     if (rp != null) {
  3802.                         // There is no need to filter these properties. For extended objects, they
  3803.                         // are accessed through our pipeline code, which always filters before
  3804.                         // returning. So any filter we do here is redundant. Note that we do
  3805.                         // pass a valid filter to a custom descriptor so it can optimize if it wants.
  3806.                         PropertyDescriptorCollection props = rp.GetExtendedProperties(_instance);
  3807.                         return props;
  3808.                     }
  3809.                    
  3810.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3811.                     if (desc == null)
  3812.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3813.                     PropertyDescriptorCollection properties = desc.GetProperties(attributes);
  3814.                     if (properties == null)
  3815.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetProperties"));
  3816.                     return properties;
  3817.                 }
  3818.                
  3819.                 /// <devdoc>
  3820.                 /// ICustomTypeDescriptor implementation.
  3821.                 /// </devdoc>
  3822.                 object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
  3823.                 {
  3824.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3825.                     // If so, we can call on it directly rather than creating another
  3826.                     // custom type descriptor
  3827.                    
  3828.                     TypeDescriptionProvider p = _node.Provider;
  3829.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3830.                    
  3831.                     if (rp != null) {
  3832.                         return rp.GetExtendedPropertyOwner(_instance, pd);
  3833.                     }
  3834.                    
  3835.                     ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
  3836.                     if (desc == null)
  3837.                         throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
  3838.                     object owner = desc.GetPropertyOwner(pd);
  3839.                     if (owner == null)
  3840.                         owner = _instance;
  3841.                     return owner;
  3842.                 }
  3843.             }
  3844.            
  3845.             /// <devdoc>
  3846.             /// The default type descriptor.
  3847.             /// </devdoc>
  3848.             private struct DefaultTypeDescriptor : ICustomTypeDescriptor
  3849.             {
  3850.                 private TypeDescriptionNode _node;
  3851.                 private Type _objectType;
  3852.                 private object _instance;
  3853.                
  3854.                 /// <devdoc>
  3855.                 /// Creates a new WalkingTypeDescriptor.
  3856.                 /// </devdoc>
  3857.                 internal DefaultTypeDescriptor(TypeDescriptionNode node, Type objectType, object instance)
  3858.                 {
  3859.                     _node = node;
  3860.                     _objectType = objectType;
  3861.                     _instance = instance;
  3862.                 }
  3863.                
  3864.                 /// <devdoc>
  3865.                 /// ICustomTypeDescriptor implementation.
  3866.                 /// </devdoc>
  3867.                 AttributeCollection ICustomTypeDescriptor.GetAttributes()
  3868.                 {
  3869.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3870.                     // If so, we can call on it directly rather than creating another
  3871.                     // custom type descriptor
  3872.                    
  3873.                     TypeDescriptionProvider p = _node.Provider;
  3874.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3875.                     AttributeCollection attrs;
  3876.                    
  3877.                     if (rp != null) {
  3878.                         attrs = rp.GetAttributes(_objectType);
  3879.                     }
  3880.                     else {
  3881.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  3882.                         if (desc == null)
  3883.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  3884.                         attrs = desc.GetAttributes();
  3885.                         if (attrs == null)
  3886.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetAttributes"));
  3887.                     }
  3888.                    
  3889.                     return attrs;
  3890.                 }
  3891.                
  3892.                 /// <devdoc>
  3893.                 /// ICustomTypeDescriptor implementation.
  3894.                 /// </devdoc>
  3895.                 string ICustomTypeDescriptor.GetClassName()
  3896.                 {
  3897.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3898.                     // If so, we can call on it directly rather than creating another
  3899.                     // custom type descriptor
  3900.                    
  3901.                     TypeDescriptionProvider p = _node.Provider;
  3902.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3903.                     string name;
  3904.                    
  3905.                     if (rp != null) {
  3906.                         name = rp.GetClassName(_objectType);
  3907.                     }
  3908.                     else {
  3909.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  3910.                         if (desc == null)
  3911.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  3912.                         name = desc.GetClassName();
  3913.                         if (name == null)
  3914.                             name = _objectType.FullName;
  3915.                     }
  3916.                    
  3917.                     return name;
  3918.                 }
  3919.                
  3920.                 /// <devdoc>
  3921.                 /// ICustomTypeDescriptor implementation.
  3922.                 /// </devdoc>
  3923.                 string ICustomTypeDescriptor.GetComponentName()
  3924.                 {
  3925.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3926.                     // If so, we can call on it directly rather than creating another
  3927.                     // custom type descriptor
  3928.                    
  3929.                     TypeDescriptionProvider p = _node.Provider;
  3930.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3931.                     string name;
  3932.                    
  3933.                     if (rp != null) {
  3934.                         name = rp.GetComponentName(_objectType, _instance);
  3935.                     }
  3936.                     else {
  3937.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  3938.                         if (desc == null)
  3939.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  3940.                         name = desc.GetComponentName();
  3941.                     }
  3942.                    
  3943.                     return name;
  3944.                 }
  3945.                
  3946.                 /// <devdoc>
  3947.                 /// ICustomTypeDescriptor implementation.
  3948.                 /// </devdoc>
  3949.                 TypeConverter ICustomTypeDescriptor.GetConverter()
  3950.                 {
  3951.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3952.                     // If so, we can call on it directly rather than creating another
  3953.                     // custom type descriptor
  3954.                    
  3955.                     TypeDescriptionProvider p = _node.Provider;
  3956.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3957.                     TypeConverter converter;
  3958.                    
  3959.                     if (rp != null) {
  3960.                         converter = rp.GetConverter(_objectType, _instance);
  3961.                     }
  3962.                     else {
  3963.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  3964.                         if (desc == null)
  3965.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  3966.                         converter = desc.GetConverter();
  3967.                         if (converter == null)
  3968.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetConverter"));
  3969.                     }
  3970.                    
  3971.                     return converter;
  3972.                 }
  3973.                
  3974.                 /// <devdoc>
  3975.                 /// ICustomTypeDescriptor implementation.
  3976.                 /// </devdoc>
  3977.                 EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
  3978.                 {
  3979.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  3980.                     // If so, we can call on it directly rather than creating another
  3981.                     // custom type descriptor
  3982.                    
  3983.                     TypeDescriptionProvider p = _node.Provider;
  3984.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  3985.                     EventDescriptor defaultEvent;
  3986.                    
  3987.                     if (rp != null) {
  3988.                         defaultEvent = rp.GetDefaultEvent(_objectType, _instance);
  3989.                     }
  3990.                     else {
  3991.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  3992.                         if (desc == null)
  3993.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  3994.                         defaultEvent = desc.GetDefaultEvent();
  3995.                     }
  3996.                    
  3997.                     return defaultEvent;
  3998.                 }
  3999.                
  4000.                 /// <devdoc>
  4001.                 /// ICustomTypeDescriptor implementation.
  4002.                 /// </devdoc>
  4003.                 PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
  4004.                 {
  4005.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  4006.                     // If so, we can call on it directly rather than creating another
  4007.                     // custom type descriptor
  4008.                    
  4009.                     TypeDescriptionProvider p = _node.Provider;
  4010.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  4011.                     PropertyDescriptor defaultProperty;
  4012.                    
  4013.                     if (rp != null) {
  4014.                         defaultProperty = rp.GetDefaultProperty(_objectType, _instance);
  4015.                     }
  4016.                     else {
  4017.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  4018.                         if (desc == null)
  4019.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  4020.                         defaultProperty = desc.GetDefaultProperty();
  4021.                     }
  4022.                    
  4023.                     return defaultProperty;
  4024.                 }
  4025.                
  4026.                 /// <devdoc>
  4027.                 /// ICustomTypeDescriptor implementation.
  4028.                 /// </devdoc>
  4029.                 object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
  4030.                 {
  4031.                     if (editorBaseType == null) {
  4032.                         throw new ArgumentNullException("editorBaseType");
  4033.                     }
  4034.                    
  4035.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  4036.                     // If so, we can call on it directly rather than creating another
  4037.                     // custom type descriptor
  4038.                    
  4039.                     TypeDescriptionProvider p = _node.Provider;
  4040.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  4041.                     object editor;
  4042.                    
  4043.                     if (rp != null) {
  4044.                         editor = rp.GetEditor(_objectType, _instance, editorBaseType);
  4045.                     }
  4046.                     else {
  4047.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  4048.                         if (desc == null)
  4049.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  4050.                         editor = desc.GetEditor(editorBaseType);
  4051.                     }
  4052.                    
  4053.                     return editor;
  4054.                 }
  4055.                
  4056.                 /// <devdoc>
  4057.                 /// ICustomTypeDescriptor implementation.
  4058.                 /// </devdoc>
  4059.                 EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
  4060.                 {
  4061.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  4062.                     // If so, we can call on it directly rather than creating another
  4063.                     // custom type descriptor
  4064.                    
  4065.                     TypeDescriptionProvider p = _node.Provider;
  4066.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  4067.                     EventDescriptorCollection events;
  4068.                    
  4069.                     if (rp != null) {
  4070.                         events = rp.GetEvents(_objectType);
  4071.                     }
  4072.                     else {
  4073.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  4074.                         if (desc == null)
  4075.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  4076.                         events = desc.GetEvents();
  4077.                         if (events == null)
  4078.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetEvents"));
  4079.                     }
  4080.                    
  4081.                     return events;
  4082.                 }
  4083.                
  4084.                 /// <devdoc>
  4085.                 /// ICustomTypeDescriptor implementation.
  4086.                 /// </devdoc>
  4087.                 EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
  4088.                 {
  4089.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  4090.                     // If so, we can call on it directly rather than creating another
  4091.                     // custom type descriptor
  4092.                    
  4093.                     TypeDescriptionProvider p = _node.Provider;
  4094.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  4095.                     EventDescriptorCollection events;
  4096.                    
  4097.                     if (rp != null) {
  4098.                         events = rp.GetEvents(_objectType);
  4099.                     }
  4100.                     else {
  4101.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  4102.                         if (desc == null)
  4103.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  4104.                         events = desc.GetEvents(attributes);
  4105.                         if (events == null)
  4106.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetEvents"));
  4107.                     }
  4108.                    
  4109.                     return events;
  4110.                 }
  4111.                
  4112.                 /// <devdoc>
  4113.                 /// ICustomTypeDescriptor implementation.
  4114.                 /// </devdoc>
  4115.                 PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
  4116.                 {
  4117.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  4118.                     // If so, we can call on it directly rather than creating another
  4119.                     // custom type descriptor
  4120.                    
  4121.                     TypeDescriptionProvider p = _node.Provider;
  4122.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  4123.                     PropertyDescriptorCollection properties;
  4124.                    
  4125.                     if (rp != null) {
  4126.                         properties = rp.GetProperties(_objectType);
  4127.                     }
  4128.                     else {
  4129.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  4130.                         if (desc == null)
  4131.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  4132.                         properties = desc.GetProperties();
  4133.                         if (properties == null)
  4134.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetProperties"));
  4135.                     }
  4136.                    
  4137.                     return properties;
  4138.                 }
  4139.                
  4140.                 /// <devdoc>
  4141.                 /// ICustomTypeDescriptor implementation.
  4142.                 /// </devdoc>
  4143.                 PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
  4144.                 {
  4145.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  4146.                     // If so, we can call on it directly rather than creating another
  4147.                     // custom type descriptor
  4148.                    
  4149.                     TypeDescriptionProvider p = _node.Provider;
  4150.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  4151.                     PropertyDescriptorCollection properties;
  4152.                    
  4153.                     if (rp != null) {
  4154.                         properties = rp.GetProperties(_objectType);
  4155.                     }
  4156.                     else {
  4157.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  4158.                         if (desc == null)
  4159.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  4160.                         properties = desc.GetProperties(attributes);
  4161.                         if (properties == null)
  4162.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetProperties"));
  4163.                     }
  4164.                    
  4165.                     return properties;
  4166.                 }
  4167.                
  4168.                 /// <devdoc>
  4169.                 /// ICustomTypeDescriptor implementation.
  4170.                 /// </devdoc>
  4171.                 object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
  4172.                 {
  4173.                     // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
  4174.                     // If so, we can call on it directly rather than creating another
  4175.                     // custom type descriptor
  4176.                    
  4177.                     TypeDescriptionProvider p = _node.Provider;
  4178.                     ReflectTypeDescriptionProvider rp = p as ReflectTypeDescriptionProvider;
  4179.                     object owner;
  4180.                    
  4181.                     if (rp != null) {
  4182.                         owner = rp.GetPropertyOwner(_objectType, _instance, pd);
  4183.                     }
  4184.                     else {
  4185.                         ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
  4186.                         if (desc == null)
  4187.                             throw new InvalidOperationException(SR.GetString(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
  4188.                         owner = desc.GetPropertyOwner(pd);
  4189.                         if (owner == null)
  4190.                             owner = _instance;
  4191.                     }
  4192.                    
  4193.                     return owner;
  4194.                 }
  4195.             }
  4196.         }
  4197.        
  4198.         /// <devdoc>
  4199.         /// This is a simple internal type that allows external parties
  4200.         /// to public ina custom type description provider for COM
  4201.         /// objects.
  4202.         /// </devdoc>
  4203.         private sealed class TypeDescriptorComObject
  4204.         {
  4205.         }
  4206.     }
  4207. }

Developer Fusion