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