Merge pull request #4248 from Unity-Technologies/boehm-gc-alloc-fixed
[mono.git] / mcs / class / referencesource / System / compmod / system / componentmodel / ReflectTypeDescriptionProvider.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="ReflectTypeDescriptionProvider.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.ComponentModel {
8
9     using System;
10     using System.Collections;
11     using System.Collections.Generic;
12     using System.Collections.Specialized;
13     using System.ComponentModel.Design;
14     using System.Diagnostics;
15     using System.Globalization;
16     using System.Reflection;
17     using System.Security;
18     using System.Security.Permissions;
19    
20     /// <devdoc>
21     ///     This type description provider provides type information through 
22     ///     reflection.  Unless someone has provided a custom type description
23     ///     provider for a type or instance, or unless an instance implements
24     ///     ICustomTypeDescriptor, any query for type information will go through
25     ///     this class.  There should be a single instance of this class associated
26     ///     with "object", as it can provide all type information for any type.
27     /// </devdoc>
28     [HostProtection(SharedState = true)]
29     internal sealed class ReflectTypeDescriptionProvider : TypeDescriptionProvider {
30
31         // Hastable of Type -> ReflectedTypeData.  ReflectedTypeData contains all
32         // of the type information we have gathered for a given type.
33         //
34         private Hashtable _typeData;
35
36         // This is the signature we look for when creating types that are generic, but
37         // want to know what type they are dealing with.  Enums are a good example of this;
38         // there is one enum converter that can work with all enums, but it needs to know
39         // the type of enum it is dealing with.
40         //
41         private static Type[] _typeConstructor = new Type[] {typeof(Type)};
42
43         // This is where we store the various converters, etc for the intrinsic types.
44         //
45         private static volatile Hashtable _editorTables;
46         private static volatile Hashtable _intrinsicTypeConverters;
47
48         // For converters, etc that are bound to class attribute data, rather than a class
49         // type, we have special key sentinel values that we put into the hash table.
50         //
51         private static object _intrinsicReferenceKey = new object();
52         private static object _intrinsicNullableKey = new object();
53
54         // The key we put into IDictionaryService to store our cache dictionary.
55         //
56         private static object _dictionaryKey = new object();
57
58         // This is a cache on top of core reflection.  The cache
59         // builds itself recursively, so if you ask for the properties
60         // on Control, Component and object are also automatically filled
61         // in.  The keys to the property and event caches are types.
62         // The keys to the attribute cache are either MemberInfos or types.
63         //
64         private static volatile Hashtable _propertyCache;
65         private static volatile Hashtable _eventCache;
66         private static volatile Hashtable _attributeCache;
67         private static volatile Hashtable _extendedPropertyCache;
68
69         // These are keys we stuff into our object cache.  We use this
70         // cache data to store extender provider info for an object.
71         //
72         private static readonly Guid _extenderProviderKey = Guid.NewGuid();
73         private static readonly Guid _extenderPropertiesKey = Guid.NewGuid();
74         private static readonly Guid _extenderProviderPropertiesKey = Guid.NewGuid();
75
76         // These are attribute that, when we discover them on interfaces, we do
77         // not merge them into the attribute set for a class.
78         private static readonly Type[] _skipInterfaceAttributeList = new Type[]
79         {
80             typeof(System.Runtime.InteropServices.GuidAttribute),
81             typeof(System.Runtime.InteropServices.ComVisibleAttribute),
82             typeof(System.Runtime.InteropServices.InterfaceTypeAttribute)
83         };
84
85
86         internal static Guid ExtenderProviderKey {
87             get {
88                 return _extenderProviderKey;
89             }
90         }
91
92
93         private static object _internalSyncObject = new object();
94         /// <devdoc>
95         ///     Creates a new ReflectTypeDescriptionProvider.  The type is the
96         ///     type we will obtain type information for.
97         /// </devdoc>
98         internal ReflectTypeDescriptionProvider()
99         {
100             TypeDescriptor.Trace("Reflect : Creating ReflectTypeDescriptionProvider");
101         }
102
103         /// <devdoc> 
104         ///      This is a table we create for intrinsic types. 
105         ///      There should be entries here ONLY for intrinsic 
106         ///      types, as all other types we should be able to 
107         ///      add attributes directly as metadata. 
108         /// </devdoc> 
109         private static Hashtable IntrinsicTypeConverters {
110             get {
111                 // It is not worth taking a lock for this -- worst case of a collision
112                 // would build two tables, one that garbage collects very quickly.
113                 //
114                 if (_intrinsicTypeConverters == null) {
115                     Hashtable temp = new Hashtable();
116
117                     // Add the intrinsics
118                     //
119                     temp[typeof(bool)] = typeof(BooleanConverter);
120                     temp[typeof(byte)] = typeof(ByteConverter);
121                     temp[typeof(SByte)] = typeof(SByteConverter);
122                     temp[typeof(char)] = typeof(CharConverter);
123                     temp[typeof(double)] = typeof(DoubleConverter);
124                     temp[typeof(string)] = typeof(StringConverter);
125                     temp[typeof(int)] = typeof(Int32Converter);
126                     temp[typeof(short)] = typeof(Int16Converter);
127                     temp[typeof(long)] = typeof(Int64Converter);
128                     temp[typeof(float)] = typeof(SingleConverter);
129                     temp[typeof(UInt16)] = typeof(UInt16Converter);
130                     temp[typeof(UInt32)] = typeof(UInt32Converter);
131                     temp[typeof(UInt64)] = typeof(UInt64Converter);
132                     temp[typeof(object)] = typeof(TypeConverter);
133                     temp[typeof(void)] = typeof(TypeConverter);
134                     temp[typeof(CultureInfo)] = typeof(CultureInfoConverter);
135                     temp[typeof(DateTime)] = typeof(DateTimeConverter);
136                     temp[typeof(DateTimeOffset)] = typeof(DateTimeOffsetConverter);
137                     temp[typeof(Decimal)] = typeof(DecimalConverter);
138                     temp[typeof(TimeSpan)] = typeof(TimeSpanConverter);
139                     temp[typeof(Guid)] = typeof(GuidConverter);
140                     temp[typeof(Array)] = typeof(ArrayConverter);
141                     temp[typeof(ICollection)] = typeof(CollectionConverter);
142                     temp[typeof(Enum)] = typeof(EnumConverter);
143
144                     // Special cases for things that are not bound to a specific type
145                     //
146                     temp[_intrinsicReferenceKey] = typeof(ReferenceConverter);
147                     temp[_intrinsicNullableKey] = typeof(NullableConverter);
148
149                     _intrinsicTypeConverters = temp;
150                 }
151                 return _intrinsicTypeConverters;
152             }
153         }
154
155         /// <devdoc>
156         ///     Adds an editor table for the given editor base type.
157         ///     ypically, editors are specified as metadata on an object. If no metadata for a
158         ///     equested editor base type can be found on an object, however, the
159         ///     ypeDescriptor will search an editor
160         ///     able for the editor type, if one can be found.
161         /// </devdoc>
162         internal static void AddEditorTable(Type editorBaseType, Hashtable table) 
163         {
164             if (editorBaseType == null)
165             {
166                 throw new ArgumentNullException("editorBaseType");
167             }
168
169             if (table == null)
170             {
171                 Debug.Fail("COMPAT: Editor table should not be null");
172                 // don't throw; RTM didn't so we can't do it either.
173             }
174
175             lock(_internalSyncObject) 
176             {
177                 if (_editorTables == null)
178                 {
179                     _editorTables = new Hashtable(4);
180                 }
181
182                 if (!_editorTables.ContainsKey(editorBaseType)) 
183                 {
184                     _editorTables[editorBaseType] = table;
185                 }
186             }
187         }
188
189         /// <devdoc>
190         ///     CreateInstance implementation.  We delegate to Activator.
191         /// </devdoc>
192         public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
193         {
194             Debug.Assert(objectType != null, "Should have arg-checked before coming in here");
195
196             object obj = null;
197             
198             if (argTypes != null)
199             {
200                 obj = SecurityUtils.SecureConstructorInvoke(objectType, argTypes, args, true, BindingFlags.ExactBinding);
201             }
202             else {
203                 if (args != null) {
204                     argTypes = new Type[args.Length];
205                     for(int idx = 0; idx < args.Length; idx++) {
206                         if (args[idx] != null) {
207                             argTypes[idx] = args[idx].GetType();
208                         }
209                         else {
210                             argTypes[idx] = typeof(object);
211                         }
212                     }
213                 }
214                 else {
215                     argTypes = new Type[0];
216                 }
217
218                 obj = SecurityUtils.SecureConstructorInvoke(objectType, argTypes, args, true);
219             }
220
221             if (obj == null) {
222                 obj = SecurityUtils.SecureCreateInstance(objectType, args);
223             }
224
225             return obj;
226         }
227
228
229         /// <devdoc> 
230         ///     Helper method to create editors and type converters. This checks to see if the
231         ///     type implements a Type constructor, and if it does it invokes that ctor. 
232         ///     Otherwise, it just tries to create the type.
233         /// </devdoc> 
234         private static object CreateInstance(Type objectType, Type callingType) {
235             object obj = SecurityUtils.SecureConstructorInvoke(objectType, _typeConstructor, new object[] {callingType}, false);
236
237             if (obj == null) {
238                 obj = SecurityUtils.SecureCreateInstance(objectType);
239             }
240
241             return obj;
242         }
243
244         /// <devdoc>
245         ///     Retrieves custom attributes.
246         /// </devdoc>
247         internal AttributeCollection GetAttributes(Type type)
248         {
249             ReflectedTypeData td = GetTypeData(type, true);
250             return td.GetAttributes();
251         }
252
253         /// <devdoc>
254         ///     Our implementation of GetCache sits on top of IDictionaryService.
255         /// </devdoc>
256         public override IDictionary GetCache(object instance)
257         {
258             IComponent comp = instance as IComponent;
259             if (comp != null && comp.Site != null)
260             {
261                 IDictionaryService ds = comp.Site.GetService(typeof(IDictionaryService)) as IDictionaryService;
262                 if (ds != null)
263                 {
264                     IDictionary dict = ds.GetValue(_dictionaryKey) as IDictionary;
265                     if (dict == null)
266                     {
267                         dict = new Hashtable();
268                         ds.SetValue(_dictionaryKey, dict);
269                     }
270                     return dict;
271                 }
272             }
273
274             return null;
275         }
276
277         /// <devdoc>
278         ///     Retrieves the class name for our type.
279         /// </devdoc>
280         internal string GetClassName(Type type)
281         {
282             ReflectedTypeData td = GetTypeData(type, true);
283             return td.GetClassName(null);
284         }
285
286         /// <devdoc>
287         ///     Retrieves the component name from the site.
288         /// </devdoc>
289         internal string GetComponentName(Type type, object instance)
290         {
291             ReflectedTypeData td = GetTypeData(type, true);
292             return td.GetComponentName(instance);
293         }
294
295         /// <devdoc>
296         ///     Retrieves the type converter.  If instance is non-null,
297         ///     it will be used to retrieve attributes.  Otherwise, _type
298         ///     will be used.
299         /// </devdoc>
300         internal TypeConverter GetConverter(Type type, object instance)
301         {
302             ReflectedTypeData td = GetTypeData(type, true);
303             return td.GetConverter(instance);
304         }
305
306         /// <devdoc>
307         ///     Return the default event. The default event is determined by the
308         ///     presence of a DefaultEventAttribute on the class.
309         /// </devdoc>
310         internal EventDescriptor GetDefaultEvent(Type type, object instance)
311         {
312             ReflectedTypeData td = GetTypeData(type, true);
313             return td.GetDefaultEvent(instance);
314         }
315
316         /// <devdoc>
317         ///     Return the default property.
318         /// </devdoc>
319         internal PropertyDescriptor GetDefaultProperty(Type type, object instance)
320         {
321             ReflectedTypeData td = GetTypeData(type, true);
322             return td.GetDefaultProperty(instance);
323         }
324
325         /// <devdoc>
326         ///     Retrieves the editor for the given base type.
327         /// </devdoc>
328         internal object GetEditor(Type type, object instance, Type editorBaseType)
329         {
330             ReflectedTypeData td = GetTypeData(type, true);
331             return td.GetEditor(instance, editorBaseType);
332         }
333
334         /// <devdoc> 
335         ///      Retrieves a default editor table for the given editor base type. 
336         /// </devdoc> 
337         private static Hashtable GetEditorTable(Type editorBaseType) {
338
339             if (_editorTables == null)
340             {
341                 lock(_internalSyncObject)
342                 {
343                     if (_editorTables == null)
344                     {
345                         _editorTables = new Hashtable(4);
346                     }
347                 }
348             }
349
350             object table = _editorTables[editorBaseType];
351             
352             if (table == null) 
353             {
354                 // Before we give up, it is possible that the
355                 // class initializer for editorBaseType hasn't 
356                 // actually run.
357                 //
358                 System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(editorBaseType.TypeHandle);
359                 table = _editorTables[editorBaseType];
360
361                 // If the table is still null, then throw a
362                 // sentinel in there so we don't
363                 // go through this again.
364                 //
365                 if (table == null)
366                 {
367                     lock (_internalSyncObject)
368                     {
369                         table = _editorTables[editorBaseType];
370                         if (table == null) 
371                         {
372                             _editorTables[editorBaseType] = _editorTables;
373                         }
374                     }
375                 }
376             }
377             
378             // Look for our sentinel value that indicates
379             // we have already tried and failed to get
380             // a table.
381             //
382             if (table == _editorTables) 
383             {
384                 table = null;
385             }
386             
387             return (Hashtable)table;
388         }
389         
390         /// <devdoc>
391         ///     Retrieves the events for this type.
392         /// </devdoc>
393         internal EventDescriptorCollection GetEvents(Type type)
394         {
395             ReflectedTypeData td = GetTypeData(type, true);
396             return td.GetEvents();
397         }
398
399         /// <devdoc>
400         ///     Retrieves custom extender attributes. We don't support
401         ///     extender attributes, so we always return an empty collection.
402         /// </devdoc>
403         internal AttributeCollection GetExtendedAttributes(object instance)
404         {
405             return AttributeCollection.Empty;
406         }
407
408         /// <devdoc>
409         ///     Retrieves the class name for our type.
410         /// </devdoc>
411         internal string GetExtendedClassName(object instance)
412         {
413             return GetClassName(instance.GetType());
414         }
415
416         /// <devdoc>
417         ///     Retrieves the component name from the site.
418         /// </devdoc>
419         internal string GetExtendedComponentName(object instance)
420         {
421             return GetComponentName(instance.GetType(), instance);
422         }
423
424         /// <devdoc>
425         ///     Retrieves the type converter.  If instance is non-null,
426         ///     it will be used to retrieve attributes.  Otherwise, _type
427         ///     will be used.
428         /// </devdoc>
429         internal TypeConverter GetExtendedConverter(object instance)
430         {
431             return GetConverter(instance.GetType(), instance);
432         }
433
434         /// <devdoc>
435         ///     Return the default event. The default event is determined by the
436         ///     presence of a DefaultEventAttribute on the class.
437         /// </devdoc>
438         internal EventDescriptor GetExtendedDefaultEvent(object instance)
439         {
440             return null; // we don't support extended events.
441         }
442
443         /// <devdoc>
444         ///     Return the default property.
445         /// </devdoc>
446         internal PropertyDescriptor GetExtendedDefaultProperty(object instance)
447         {
448             return null; // extender properties are never the default.
449         }
450
451         /// <devdoc>
452         ///     Retrieves the editor for the given base type.
453         /// </devdoc>
454         internal object GetExtendedEditor(object instance, Type editorBaseType)
455         {
456             return GetEditor(instance.GetType(), instance, editorBaseType);
457         }
458         
459         /// <devdoc>
460         ///     Retrieves the events for this type.
461         /// </devdoc>
462         internal EventDescriptorCollection GetExtendedEvents(object instance)
463         {
464             return EventDescriptorCollection.Empty;
465         }
466
467         /// <devdoc>
468         ///     Retrieves the properties for this type.
469         /// </devdoc>
470         internal PropertyDescriptorCollection GetExtendedProperties(object instance)
471         {
472             // Is this object a sited component?  If not, then it
473             // doesn't have any extender properties.
474             //
475             Type componentType = instance.GetType();
476
477             // Check the component for extender providers.  We prefer
478             // IExtenderListService, but will use the container if that's
479             // all we have.  In either case, we check the list of extenders
480             // against previously stored data in the object cache.  If
481             // the cache is up to date, we just return the extenders in the
482             // cache.
483             //
484             IExtenderProvider[] extenders = GetExtenderProviders(instance);
485             IDictionary cache = TypeDescriptor.GetCache(instance);
486
487             if (extenders.Length == 0)
488             {
489                 return PropertyDescriptorCollection.Empty;
490             }
491
492             // Ok, we have a set of extenders.  Now, check to see if there
493             // are properties already in our object cache.  If there aren't,
494             // then we will need to create them.
495             //
496             PropertyDescriptorCollection properties = null;
497
498             if (cache != null)
499             {
500                 properties = cache[_extenderPropertiesKey] as PropertyDescriptorCollection;
501             }
502
503             if (properties != null)
504             {
505                 return properties;
506             }
507
508             // Unlike normal properties, it is fine for there to be properties with
509             // duplicate names here.  
510             //
511             ArrayList propertyList = null;
512
513             for (int idx = 0; idx < extenders.Length; idx++)
514             {
515                 PropertyDescriptor[] propertyArray = ReflectGetExtendedProperties(extenders[idx]);
516
517                 if (propertyList == null)
518                 {
519                     propertyList = new ArrayList(propertyArray.Length * extenders.Length);
520                 }
521
522                 for (int propIdx = 0; propIdx < propertyArray.Length; propIdx++)
523                 {
524                     PropertyDescriptor prop = propertyArray[propIdx];
525                     ExtenderProvidedPropertyAttribute eppa = prop.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute;
526
527                     Debug.Assert(eppa != null, "Extender property " + prop.Name + " has no provider attribute.  We will skip it.");
528                     if (eppa != null)
529                     {
530                         Type receiverType = eppa.ReceiverType;
531                         if (receiverType != null) 
532                         {
533
534                             if (receiverType.IsAssignableFrom(componentType)) 
535                             {
536                                 propertyList.Add(prop);
537                             }
538                         }
539                     }
540                 }
541             }
542
543             // propertyHash now contains ExtendedPropertyDescriptor objects
544             // for each extended property.
545             //
546             if (propertyList != null)
547             {
548                 TypeDescriptor.Trace("Extenders : Allocating property collection for {0} properties", propertyList.Count);
549                 PropertyDescriptor[] fullArray = new PropertyDescriptor[propertyList.Count];
550                 propertyList.CopyTo(fullArray, 0);
551                 properties = new PropertyDescriptorCollection(fullArray, true);
552             }
553             else
554             {
555                 properties = PropertyDescriptorCollection.Empty;
556             }
557
558             if (cache != null)
559             {
560                 TypeDescriptor.Trace("Extenders : caching extender results");
561                 cache[_extenderPropertiesKey] = properties;
562             }
563
564             return properties;
565         }
566
567         protected internal override IExtenderProvider[] GetExtenderProviders(object instance)
568         {
569             if (instance == null)
570             {
571                 throw new ArgumentNullException("instance");
572             }
573
574             IComponent component = instance as IComponent;
575             if (component != null && component.Site != null)
576             {
577                 IExtenderListService extenderList = component.Site.GetService(typeof(IExtenderListService)) as IExtenderListService;
578                 IDictionary cache = TypeDescriptor.GetCache(instance);
579
580                 if (extenderList != null)
581                 {
582                     return GetExtenders(extenderList.GetExtenderProviders(), instance, cache);
583                 }
584                 else
585                 {
586                     IContainer cont = component.Site.Container;
587                     if (cont != null)
588                     {
589                         return GetExtenders(cont.Components, instance, cache);
590                     }
591                 }
592             }
593             return new IExtenderProvider[0];
594         }
595
596         /// <devdoc>
597         ///     GetExtenders builds a list of extender providers from
598         ///     a collection of components.  It validates the extenders
599         ///     against any cached collection of extenders in the 
600         ///     cache.  If there is a discrepancy, this will erase
601         ///     any cached extender properties from the cache and
602         ///     save the updated extender list.  If there is no
603         ///     discrepancy this will simply return the cached list.
604         /// </devdoc>
605         private static IExtenderProvider[] GetExtenders(ICollection components, object instance, IDictionary cache)
606         {
607             bool newExtenders = false;
608             int extenderCount = 0;
609             IExtenderProvider[] existingExtenders = null;
610     
611             //CanExtend is expensive. We will remember results of CanExtend for the first 64 extenders and using "long canExtend" as a bit vector.
612             // we want to avoid memory allocation as well so we don't use some more sophisticated data structure like an array of booleans
613             UInt64 canExtend = 0;
614             int maxCanExtendResults = 64;
615             // currentExtenders is what we intend to return.  If the caller passed us
616             // the return value from IExtenderListService, components will already be
617             // an IExtenderProvider[].  If not, then we must treat components as an
618             // opaque collection.  We spend a great deal of energy here to avoid
619             // copying or allocating memory because this method is called every
620             // time a component is asked for its properties.
621             IExtenderProvider[] currentExtenders = components as IExtenderProvider[];
622
623             if (cache != null)
624             {
625                 existingExtenders = cache[_extenderProviderKey] as IExtenderProvider[];
626             }
627
628             if (existingExtenders == null)
629             {
630                 newExtenders = true;
631             }
632
633             int curIdx = 0;
634             int idx = 0;
635            
636             if (currentExtenders != null)
637             {
638                 for (curIdx = 0; curIdx < currentExtenders.Length; curIdx++)
639                 {
640                     if (currentExtenders[curIdx].CanExtend(instance))
641                     {
642                         extenderCount++;
643                         // Performance:We would like to call CanExtend as little as possible therefore we remember its result
644                         if (curIdx < maxCanExtendResults)
645                             canExtend |= (UInt64)1 << curIdx;
646                         if (!newExtenders && (idx >= existingExtenders.Length || currentExtenders[curIdx] != existingExtenders[idx++]))
647                         {
648                             newExtenders = true;
649                         }
650                     }
651                 }
652             }
653             else if (components != null)
654             {
655                 foreach(object obj in components)
656                 {
657                     IExtenderProvider prov = obj as IExtenderProvider;
658                     if (prov != null && prov.CanExtend(instance))
659                     {
660                         extenderCount++;
661                         if (curIdx < maxCanExtendResults)
662                             canExtend |= (UInt64)1<<curIdx;
663                         if (!newExtenders && (idx >= existingExtenders.Length || prov != existingExtenders[idx++]))
664                         {
665                             newExtenders = true;
666                         }
667                     }
668                     curIdx++;
669                 }
670             }
671             if (existingExtenders != null && extenderCount != existingExtenders.Length)
672             {
673                 newExtenders = true;
674             }
675             if (newExtenders)
676             {
677                 TypeDescriptor.Trace("Extenders : object has new extenders : {0}", instance.GetType().Name);
678                 TypeDescriptor.Trace("Extenders : Identified {0} extender providers", extenderCount);
679                 if (currentExtenders == null || extenderCount != currentExtenders.Length)
680                 {
681                     IExtenderProvider[] newExtenderArray = new IExtenderProvider[extenderCount];
682
683                     curIdx = 0;
684                     idx = 0;
685
686                     if (currentExtenders != null && extenderCount > 0)
687                     {
688                         while(curIdx < currentExtenders.Length)
689                         { 
690                             if ((curIdx < maxCanExtendResults && (canExtend & ((UInt64)1 << curIdx)) != 0 )|| 
691                                             (curIdx >= maxCanExtendResults && currentExtenders[curIdx].CanExtend(instance)))
692                             {
693                                 Debug.Assert(idx < extenderCount, "There are more extenders than we expect");
694                                 newExtenderArray[idx++] = currentExtenders[curIdx];
695                             }
696                             curIdx++;                      
697                         }
698                         Debug.Assert(idx == extenderCount, "Wrong number of extenders");
699                     }
700                     else if (extenderCount > 0)
701                     {
702                         IEnumerator componentEnum = components.GetEnumerator();
703                         while(componentEnum.MoveNext())
704                         {
705                             IExtenderProvider p = componentEnum.Current as IExtenderProvider;
706
707                             if (p != null && ((curIdx < maxCanExtendResults && (canExtend & ((UInt64)1 << curIdx)) != 0) ||
708                                                 (curIdx >= maxCanExtendResults && p.CanExtend(instance))))
709                             {
710                                 Debug.Assert(idx < extenderCount, "There are more extenders than we expect");
711                                 newExtenderArray[idx++] = p;
712                             }
713                             curIdx++;
714                         }
715                         Debug.Assert(idx == extenderCount, "Wrong number of extenders");
716                     }
717                     currentExtenders = newExtenderArray;
718                 }
719
720                 if (cache != null)
721                 {
722                     TypeDescriptor.Trace("Extenders : caching extender provider results");
723                     cache[_extenderProviderKey] = currentExtenders;
724                     cache.Remove(_extenderPropertiesKey);
725                 }
726             }
727             else
728             {
729                 currentExtenders = existingExtenders;
730             }
731             return currentExtenders;
732         }
733
734         /// <devdoc>
735         ///     Retrieves the owner for a property.
736         /// </devdoc>
737         internal object GetExtendedPropertyOwner(object instance, PropertyDescriptor pd)
738         {
739             return GetPropertyOwner(instance.GetType(), instance, pd);
740         }
741
742         //////////////////////////////////////////////////////////
743         /// <devdoc>
744         ///     Provides a type descriptor for the given object.  We only support this
745         ///     if the object is a component that 
746         /// </devdoc>
747         public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
748         {
749             Debug.Fail("This should never be invoked.  TypeDescriptionNode should wrap for us.");
750             return null;
751         }
752
753         /// <devdoc>
754         ///     The name of the specified component, or null if the component has no name.
755         ///     In many cases this will return the same value as GetComponentName. If the
756         ///     component resides in a nested container or has other nested semantics, it may
757         ///     return a different fully qualfied name.
758         ///
759         ///     If not overridden, the default implementation of this method will call
760         ///     GetComponentName.
761         /// </devdoc>
762         public override string GetFullComponentName(object component) {
763             IComponent comp = component as IComponent;
764             if (comp != null) {
765                 INestedSite ns = comp.Site as INestedSite;
766                 if (ns != null) {
767                     return ns.FullName;
768                 }
769             }
770
771             return TypeDescriptor.GetComponentName(component);
772         }
773
774         /// <devdoc>
775         ///     Returns an array of types we have populated metadata for that live
776         ///     in the current module.
777         /// </devdoc>
778         internal Type[] GetPopulatedTypes(Module module) {
779             ArrayList typeList = new ArrayList();;
780
781             foreach(DictionaryEntry de in _typeData) {
782                 Type type = (Type)de.Key;
783                 ReflectedTypeData typeData = (ReflectedTypeData)de.Value;
784
785                 if (type.Module == module && typeData.IsPopulated) {
786                     typeList.Add(type);
787                 }
788             }
789
790             return (Type[])typeList.ToArray(typeof(Type));
791         }
792
793         /// <devdoc>
794         ///     Retrieves the properties for this type.
795         /// </devdoc>
796         internal PropertyDescriptorCollection GetProperties(Type type)
797         {
798             ReflectedTypeData td = GetTypeData(type, true);
799             return td.GetProperties();
800         }
801
802         /// <devdoc>
803         ///     Retrieves the owner for a property.
804         /// </devdoc>
805         internal object GetPropertyOwner(Type type, object instance, PropertyDescriptor pd)
806         {
807             return TypeDescriptor.GetAssociation(type, instance);
808         }
809
810         /// <devdoc>
811         ///     Returns an Type for the given type.  Since type implements IReflect,
812         ///     we just return objectType.
813         /// </devdoc>
814         public override Type GetReflectionType(Type objectType, object instance)
815         {
816             Debug.Assert(objectType != null, "Should have arg-checked before coming in here");
817             return objectType;
818         }
819
820         /// <devdoc>
821         ///     Returns the type data for the given type, or
822         ///     null if there is no type data for the type yet and
823         ///     createIfNeeded is false.
824         /// </devdoc>
825         private ReflectedTypeData GetTypeData(Type type, bool createIfNeeded) {
826
827             ReflectedTypeData td = null;
828
829             if (_typeData != null) {
830                 td = (ReflectedTypeData)_typeData[type];
831                 if (td != null) {
832                     return td;
833                 }
834             }
835
836             lock (_internalSyncObject) {
837                 if (_typeData != null) {
838                     td = (ReflectedTypeData)_typeData[type];
839                 }
840
841                 if (td == null && createIfNeeded) {
842                     td = new ReflectedTypeData(type);
843                     if (_typeData == null) {
844                         _typeData = new Hashtable();
845                     }
846                     _typeData[type] = td;
847                 }
848             }
849
850             return td;
851         }
852
853         /// <devdoc>
854         ///     This method returns a custom type descriptor for the given type / object.  
855         ///     The objectType parameter is always valid, but the instance parameter may 
856         ///     be null if no instance was passed to TypeDescriptor.  The method should 
857         ///     return a custom type descriptor for the object.  If the method is not 
858         ///     interested in providing type information for the object it should 
859         ///     return null.
860         /// </devdoc>
861         public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
862         {
863             Debug.Fail("This should never be invoked.  TypeDescriptionNode should wrap for us.");
864             return null;
865         }
866     
867         /// <devdoc>
868         ///     Retrieves a type from a name.
869         /// </devdoc>
870         private static Type GetTypeFromName(string typeName) 
871         {
872             Type t = Type.GetType(typeName);
873
874             if (t == null) 
875             {
876                 int commaIndex = typeName.IndexOf(',');
877
878                 if (commaIndex != -1)
879                 {
880                     // At design time, it's possible for us to reuse
881                     // an assembly but add new types.  The app domain
882                     // will cache the assembly based on identity, however,
883                     // so it could be looking in the previous version
884                     // of the assembly and not finding the type.  We work
885                     // around this by looking for the non-assembly qualified
886                     // name, which causes the domain to raise a type 
887                     // resolve event.
888                     //
889                     t = Type.GetType(typeName.Substring(0, commaIndex));
890                 }
891             }
892
893             return t;
894         }
895
896         /// <devdoc>
897         ///     This method returns true if the data cache in this reflection 
898         ///     type descriptor has data in it.
899         /// </devdoc>
900         internal bool IsPopulated(Type type)
901         {
902             ReflectedTypeData td = GetTypeData(type, false);
903             if (td != null) {
904                 return td.IsPopulated;
905             }
906             return false;
907         }
908
909         /// <devdoc>
910         ///     Static helper API around reflection to get and cache
911         ///     custom attributes.  This does not recurse, but it will
912         ///     walk interfaces on the type.  Interfaces are added 
913         ///     to the end, so merging should be done from length - 1
914         ///     to 0.
915         /// </devdoc>
916         private static Attribute[] ReflectGetAttributes(Type type)
917         {
918             if (_attributeCache == null)
919             {
920                 lock (_internalSyncObject)
921                 {
922                     if (_attributeCache == null)
923                     {
924                         _attributeCache = new Hashtable();
925                     }
926                 }
927             }
928
929             Attribute[] attrs = (Attribute[])_attributeCache[type];
930             if (attrs != null)
931             {
932                 return attrs;
933             }
934
935             lock (_internalSyncObject)
936             {
937                 attrs = (Attribute[])_attributeCache[type];
938                 if (attrs == null)
939                 {
940                     TypeDescriptor.Trace("Attributes : Building attributes for {0}", type.Name);
941
942                     // Get the type's attributes.
943                     //
944                     object[] typeAttrs = type.GetCustomAttributes(typeof(Attribute), false);
945
946                     attrs = new Attribute[typeAttrs.Length];
947                     typeAttrs.CopyTo(attrs, 0);
948
949                     _attributeCache[type] = attrs;
950                 }
951             }
952
953             return attrs;
954         }
955
956         /// <devdoc>
957         ///     Static helper API around reflection to get and cache
958         ///     custom attributes.  This does not recurse to the base class.
959         /// </devdoc>
960         internal static Attribute[] ReflectGetAttributes(MemberInfo member)
961         {
962             if (_attributeCache == null)
963             {
964                 lock (_internalSyncObject)
965                 {
966                     if (_attributeCache == null)
967                     {
968                         _attributeCache = new Hashtable();
969                     }
970                 }
971             }
972
973             Attribute[] attrs = (Attribute[])_attributeCache[member];
974             if (attrs != null)
975             {
976                 return attrs;
977             }
978
979             lock (_internalSyncObject)
980             {
981                 attrs = (Attribute[])_attributeCache[member];
982                 if (attrs == null)
983                 {
984                     // Get the member's attributes.
985                     //
986                     object[] memberAttrs = member.GetCustomAttributes(typeof(Attribute), false);
987                     attrs = new Attribute[memberAttrs.Length];
988                     memberAttrs.CopyTo(attrs, 0);
989                     _attributeCache[member] = attrs;
990                 }
991             }
992
993             return attrs;
994         }
995
996         /// <devdoc>
997         ///     Static helper API around reflection to get and cache
998         ///     events.  This does not recurse to the base class.
999         /// </devdoc>
1000         private static EventDescriptor[] ReflectGetEvents(Type type)
1001         {
1002             if (_eventCache == null)
1003             {
1004                 lock (_internalSyncObject)
1005                 {
1006                     if (_eventCache == null)
1007                     {
1008                         _eventCache = new Hashtable();
1009                     }
1010                 }
1011             }
1012
1013             EventDescriptor[] events = (EventDescriptor[])_eventCache[type];
1014             if (events != null)
1015             {
1016                 return events;
1017             }
1018
1019             lock (_internalSyncObject)
1020             {
1021                 events = (EventDescriptor[])_eventCache[type];
1022                 if (events == null)
1023                 {
1024                     BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
1025                     TypeDescriptor.Trace("Events : Building events for {0}", type.Name);
1026
1027                     // Get the type's events.  Events may have their add and
1028                     // remove methods individually overridden in a derived
1029                     // class, but at some point in the base class chain both
1030                     // methods must exist.  If we find an event that doesn't
1031                     // have both add and remove, we skip it here, because it
1032                     // will be picked up in our base class scan.
1033                     //
1034                     EventInfo[] eventInfos = type.GetEvents(bindingFlags);
1035                     events = new EventDescriptor[eventInfos.Length];
1036                     int eventCount = 0;
1037
1038                     for (int idx = 0; idx < eventInfos.Length; idx++)
1039                     {
1040                         EventInfo eventInfo = eventInfos[idx];
1041
1042                         // GetEvents returns events that are on nonpublic types
1043                         // if those types are from our assembly.  Screen these.
1044                         // 
1045                         if ((!(eventInfo.DeclaringType.IsPublic || eventInfo.DeclaringType.IsNestedPublic)) && (eventInfo.DeclaringType.Assembly == typeof(ReflectTypeDescriptionProvider).Assembly)) {
1046                             Debug.Fail("Hey, assumption holds true.  Rip this assert.");
1047                             continue;
1048                         }
1049
1050                         MethodInfo addMethod = eventInfo.GetAddMethod();
1051                         MethodInfo removeMethod = eventInfo.GetRemoveMethod();
1052
1053                         if (addMethod != null && removeMethod != null)
1054                         {
1055                             events[eventCount++] = new ReflectEventDescriptor(type, eventInfo);
1056                         }
1057                     }
1058
1059                     if (eventCount != events.Length)
1060                     {
1061                         EventDescriptor[] newEvents = new EventDescriptor[eventCount];
1062                         Array.Copy(events, 0, newEvents, 0, eventCount);
1063                         events = newEvents;
1064                     }
1065
1066                     #if DEBUG
1067                     foreach(EventDescriptor dbgEvent in events)
1068                     {
1069                         Debug.Assert(dbgEvent != null, "Holes in event array for type " + type);
1070                     }
1071                     #endif
1072                     _eventCache[type] = events;
1073                 }
1074             }
1075
1076             return events;
1077         }
1078
1079         /// <devdoc>
1080         ///     This performs the actual reflection needed to discover
1081         ///     extender properties.  If object caching is supported this
1082         ///     will maintain a cache of property descriptors on the
1083         ///     extender provider.  Extender properties are actually two
1084         ///     property descriptors in one.  There is a chunk of per-class
1085         ///     data in a ReflectPropertyDescriptor that defines the
1086         ///     parameter types and get and set methods of the extended property,
1087         ///     and there is an ExtendedPropertyDescriptor that combines this
1088         ///     with an extender provider object to create what looks like a
1089         ///     normal property.  ReflectGetExtendedProperties maintains two 
1090         ///     separate caches for these two sets:  a static one for the
1091         ///     ReflectPropertyDescriptor values that don't change for each
1092         ///     provider instance, and a per-provider cache that contains
1093         ///     the ExtendedPropertyDescriptors.
1094         /// </devdoc>
1095         private static PropertyDescriptor[] ReflectGetExtendedProperties(IExtenderProvider provider)
1096         {
1097             IDictionary cache = TypeDescriptor.GetCache(provider);
1098             PropertyDescriptor[] properties;
1099
1100             if (cache != null)
1101             {
1102                 properties = cache[_extenderProviderPropertiesKey] as PropertyDescriptor[];
1103                 if (properties != null)
1104                 {
1105                     return properties;
1106                 }
1107             }
1108
1109             // Our per-instance cache missed.  We have never seen this instance of the
1110             // extender provider before.  See if we can find our class-based
1111             // property store.
1112             //
1113             if (_extendedPropertyCache == null)
1114             {
1115                 lock (_internalSyncObject)
1116                 {
1117                     if (_extendedPropertyCache == null)
1118                     {
1119                         _extendedPropertyCache = new Hashtable();
1120                     }
1121                 }
1122             }
1123
1124             Type providerType = provider.GetType();
1125             ReflectPropertyDescriptor[] extendedProperties = (ReflectPropertyDescriptor[])_extendedPropertyCache[providerType];
1126             if (extendedProperties == null)
1127             {
1128                 lock (_internalSyncObject)
1129                 {
1130                     extendedProperties = (ReflectPropertyDescriptor[])_extendedPropertyCache[providerType];
1131
1132                     // Our class-based property store failed as well, so we need to build up the set of
1133                     // extended properties here.
1134                     //
1135                     if (extendedProperties == null)
1136                     {
1137                         AttributeCollection attributes = TypeDescriptor.GetAttributes(providerType);
1138                         ArrayList extendedList = new ArrayList(attributes.Count);
1139
1140                         foreach(Attribute attr in attributes) 
1141                         {
1142                             ProvidePropertyAttribute provideAttr = attr as ProvidePropertyAttribute;
1143
1144                             if (provideAttr != null) 
1145                             {
1146                                 Type receiverType = GetTypeFromName(provideAttr.ReceiverTypeName);
1147
1148                                 if (receiverType != null) 
1149                                 {
1150                                     MethodInfo getMethod = providerType.GetMethod("Get" + provideAttr.PropertyName, new Type[] {receiverType});
1151
1152                                     if (getMethod != null && !getMethod.IsStatic && getMethod.IsPublic) 
1153                                     {
1154                                         MethodInfo setMethod = providerType.GetMethod("Set" + provideAttr.PropertyName, new Type[] {receiverType, getMethod.ReturnType});
1155
1156                                         if (setMethod != null && (setMethod.IsStatic || !setMethod.IsPublic)) 
1157                                         {
1158                                             setMethod = null;
1159                                         }
1160
1161                                         extendedList.Add(new ReflectPropertyDescriptor(providerType, provideAttr.PropertyName, getMethod.ReturnType, receiverType, getMethod, setMethod, null));
1162                                     }
1163                                 }
1164                             }
1165                         }
1166
1167                         extendedProperties = new ReflectPropertyDescriptor[extendedList.Count];
1168                         extendedList.CopyTo(extendedProperties, 0);
1169                         _extendedPropertyCache[providerType] = extendedProperties;
1170                     }
1171                 }
1172             }
1173
1174             // Now that we have our extended properties we can build up a list of callable properties.  These can be 
1175             // returned to the user.
1176             //
1177             properties = new PropertyDescriptor[extendedProperties.Length];
1178             for (int idx = 0; idx < extendedProperties.Length; idx++)
1179             {
1180                 Attribute[] attrs = null;
1181                 IComponent comp = provider as IComponent;
1182                 if (comp == null || comp.Site == null)
1183                 {
1184                     attrs = new Attribute[] {DesignOnlyAttribute.Yes};
1185                 }
1186
1187                 ReflectPropertyDescriptor  rpd = extendedProperties[idx];
1188                 ExtendedPropertyDescriptor epd = new ExtendedPropertyDescriptor(rpd, rpd.ExtenderGetReceiverType(), provider, attrs);
1189                 properties[idx] = epd;
1190             }
1191
1192             if (cache != null)
1193             {
1194                 cache[_extenderProviderPropertiesKey] = properties;
1195             }
1196
1197             return properties;
1198         }
1199
1200         /// <devdoc>
1201         ///     Static helper API around reflection to get and cache
1202         ///     properties. This does not recurse to the base class.
1203         /// </devdoc>
1204         private static PropertyDescriptor[] ReflectGetProperties(Type type)
1205         {
1206             if (_propertyCache == null)
1207             {
1208                 lock(_internalSyncObject)
1209                 {
1210                     if (_propertyCache == null)
1211                     {
1212                         _propertyCache = new Hashtable();
1213                     }
1214                 }
1215             }
1216
1217             PropertyDescriptor[] properties = (PropertyDescriptor[])_propertyCache[type];
1218             if (properties != null)
1219             {
1220                 return properties;
1221             }
1222
1223             lock (_internalSyncObject)
1224             {
1225                 properties = (PropertyDescriptor[])_propertyCache[type];
1226
1227                 if (properties == null)
1228                 {
1229                     BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
1230                     TypeDescriptor.Trace("Properties : Building properties for {0}", type.Name);
1231
1232                     // Get the type's properties.  Properties may have their
1233                     // get and set methods individually overridden in a derived
1234                     // class, so if we find a missing method we need to walk
1235                     // down the base class chain to find it.  We actually merge
1236                     // "new" properties of the same name, so we must preserve
1237                     // the member info for each method individually.
1238                     //
1239                     PropertyInfo[] propertyInfos = type.GetProperties(bindingFlags);
1240                     properties = new PropertyDescriptor[propertyInfos.Length];
1241                     int propertyCount = 0;
1242
1243                
1244                     for (int idx = 0; idx < propertyInfos.Length; idx++)
1245                     {
1246                         PropertyInfo propertyInfo = propertyInfos[idx];
1247
1248                         // Today we do not support parameterized properties.
1249                         // 
1250                         if (propertyInfo.GetIndexParameters().Length > 0) {
1251                             continue;
1252                         } 
1253
1254                         MethodInfo getMethod = propertyInfo.GetGetMethod();
1255                         MethodInfo setMethod = propertyInfo.GetSetMethod();
1256                         string name = propertyInfo.Name;
1257
1258                         // If the property only overrode "set", then we don't
1259                         // pick it up here.  Rather, we just merge it in from
1260                         // the base class list.
1261       
1262
1263                         // If a property had at least a get method, we consider it.  We don't
1264                         // consider write-only properties.
1265                         //
1266                         if (getMethod != null)
1267                         {
1268                             properties[propertyCount++] = new ReflectPropertyDescriptor(type, name, 
1269                                                                                     propertyInfo.PropertyType, 
1270                                                                                     propertyInfo, getMethod, 
1271                                                                                     setMethod, null);
1272                         }
1273                     }
1274
1275                
1276                     if (propertyCount != properties.Length)
1277                     {
1278                         PropertyDescriptor[] newProperties = new PropertyDescriptor[propertyCount];
1279                         Array.Copy(properties, 0, newProperties, 0, propertyCount);
1280                         properties = newProperties;
1281                     }
1282
1283                     #if DEBUG
1284                     foreach(PropertyDescriptor dbgProp in properties)
1285                     {
1286                         Debug.Assert(dbgProp != null, "Holes in property array for type " + type);
1287                     }
1288                     #endif
1289                     _propertyCache[type] = properties;
1290                 }
1291             }
1292
1293             return properties;
1294         }
1295
1296         /// <devdoc>
1297         ///     Refreshes the contents of this type descriptor.  This does not
1298         ///     actually requery, but it will clear our state so the next
1299         ///     query re-populates.
1300         /// </devdoc>
1301         internal void Refresh(Type type)
1302         {
1303             ReflectedTypeData td = GetTypeData(type, false);
1304             if (td != null) {
1305                 td.Refresh();
1306             }
1307         }
1308
1309         /// <devdoc> 
1310         ///      Searches the provided intrinsic hashtable for a match with the object type. 
1311         ///      At the beginning, the hashtable contains types for the various converters. 
1312         ///      As this table is searched, the types for these objects 
1313         ///      are replaced with instances, so we only create as needed.  This method 
1314         ///      does the search up the base class hierarchy and will create instances 
1315         ///      for types as needed.  These instances are stored back into the table 
1316         ///      for the base type, and for the original component type, for fast access. 
1317         /// </devdoc> 
1318         private static object SearchIntrinsicTable(Hashtable table, Type callingType) 
1319         {
1320             object hashEntry = null;
1321
1322             // We take a lock on this table.  Nothing in this code calls out to
1323             // other methods that lock, so it should be fairly safe to grab this
1324             // lock.  Also, this allows multiple intrinsic tables to be searched
1325             // at once.
1326             //
1327             lock(table) 
1328             {
1329                 Type baseType = callingType;
1330                 while (baseType != null && baseType != typeof(object)) 
1331                 {
1332                     hashEntry = table[baseType];
1333
1334                     // If the entry is a late-bound type, then try to
1335                     // resolve it.
1336                     //
1337                     string typeString = hashEntry as string;
1338                     if (typeString != null) 
1339                     {
1340                         hashEntry = Type.GetType(typeString);
1341                         if (hashEntry != null) 
1342                         {
1343                             table[baseType] = hashEntry;
1344                         }
1345                     }
1346
1347                     if (hashEntry != null) 
1348                     {
1349                         break;
1350                     }
1351
1352                     baseType = baseType.BaseType;
1353                 }
1354
1355                 // Now make a scan through each value in the table, looking for interfaces.
1356                 // If we find one, see if the object implements the interface.
1357                 //
1358                 if (hashEntry == null) 
1359                 {
1360
1361                     foreach(DictionaryEntry de in table)
1362                     {
1363                         Type keyType = de.Key as Type;
1364
1365                         if (keyType != null && keyType.IsInterface && keyType.IsAssignableFrom(callingType)) 
1366                         {
1367
1368                             hashEntry = de.Value;
1369                             string typeString = hashEntry as string;
1370
1371                             if (typeString != null) 
1372                             {
1373                                 hashEntry = Type.GetType(typeString);
1374                                 if (hashEntry != null) 
1375                                 {
1376                                     table[callingType] = hashEntry;
1377                                 }
1378                             }
1379
1380                             if (hashEntry != null) 
1381                             {
1382                                 break;
1383                             }
1384                         }
1385                     }
1386                 }
1387
1388                 // Special case converters
1389                 //
1390                 if (hashEntry == null)
1391                 {
1392                     if (callingType.IsGenericType && callingType.GetGenericTypeDefinition() == typeof(Nullable<>))
1393                     {
1394                         // Check if it is a nullable value
1395                         hashEntry = table[_intrinsicNullableKey];
1396                     }
1397                     else if (callingType.IsInterface)
1398                     {
1399                         // Finally, check to see if the component type is some unknown interface.
1400                         // We have a custom converter for that.
1401                         hashEntry = table[_intrinsicReferenceKey];
1402                     }
1403                 }
1404
1405                 // Interfaces do not derive from object, so we
1406                 // must handle the case of no hash entry here.
1407                 //
1408                 if (hashEntry == null) 
1409                 {
1410                     hashEntry = table[typeof(object)];
1411                 }
1412
1413                 // If the entry is a type, create an instance of it and then
1414                 // replace the entry.  This way we only need to create once.
1415                 // We can only do this if the object doesn't want a type
1416                 // in its constructor.
1417                 //
1418                 Type type = hashEntry as Type;
1419
1420                 if (type != null) 
1421                 {
1422                     hashEntry = CreateInstance(type, callingType);
1423                     if (type.GetConstructor(_typeConstructor) == null) 
1424                     {
1425                         table[callingType] = hashEntry;
1426                     }
1427                 }
1428             }
1429
1430             return hashEntry;
1431         }
1432
1433         /// <devdoc>
1434         ///     This class contains all the reflection information for a
1435         ///     given type.
1436         /// </devdoc>
1437         private class ReflectedTypeData {
1438
1439             private Type                            _type;
1440             private AttributeCollection             _attributes;
1441             private EventDescriptorCollection       _events;
1442             private PropertyDescriptorCollection    _properties;
1443             private TypeConverter                   _converter;
1444             private object[]                        _editors;
1445             private Type[]                          _editorTypes;
1446             private int                             _editorCount;
1447
1448             internal ReflectedTypeData(Type type) {
1449                 _type = type;
1450                 TypeDescriptor.Trace("Reflect : Creating ReflectedTypeData for {0}", type.Name);
1451             }
1452
1453             /// <devdoc>
1454             ///     This method returns true if the data cache in this reflection 
1455             ///     type descriptor has data in it.
1456             /// </devdoc>
1457             internal bool IsPopulated
1458             {
1459                 get
1460                 {
1461                     return (_attributes != null) | (_events != null) | (_properties != null);
1462                 }
1463             }
1464
1465             /// <devdoc>
1466             ///     Retrieves custom attributes.
1467             /// </devdoc>
1468             internal AttributeCollection GetAttributes()
1469             {
1470                 // Worst case collision scenario:  we don't want the perf hit
1471                 // of taking a lock, so if we collide we will query for
1472                 // attributes twice.  Not a big deal.
1473                 //
1474                 if (_attributes == null)
1475                 {
1476                     TypeDescriptor.Trace("Attributes : Building collection for {0}", _type.Name);
1477
1478                     // Obtaining attributes follows a very critical order: we must take care that
1479                     // we merge attributes the right way.  Consider this:
1480                     //
1481                     // [A4]
1482                     // interface IBase;
1483                     //
1484                     // [A3]
1485                     // interface IDerived;
1486                     //
1487                     // [A2]
1488                     // class Base : IBase;
1489                     //
1490                     // [A1]
1491                     // class Derived : Base, IDerived
1492                     //
1493                     // Calling GetAttributes on type Derived must merge attributes in the following
1494                     // order:  A1 - A4.  Interfaces always lose to types, and interfaces and types
1495                     // must be merged in the same order.  At the same time, we must be careful
1496                     // that we don't always go through reflection here, because someone could have
1497                     // created a custom provider for a type.  Because there is only one instance
1498                     // of ReflectTypeDescriptionProvider created for typeof(object), if our code
1499                     // is invoked here we can be sure that there is no custom provider for
1500                     // _type all the way up the base class chain.
1501                     // We cannot be sure that there is no custom provider for
1502                     // interfaces that _type implements, however, because they are not derived
1503                     // from _type.  So, for interfaces, we must go through TypeDescriptor
1504                     // again to get the interfaces attributes.  
1505
1506                     // Get the type's attributes. This does not recurse up the base class chain.
1507                     // We append base class attributes to this array so when walking we will
1508                     // walk from Length - 1 to zero.
1509                     //
1510                     Attribute[] attrArray = ReflectTypeDescriptionProvider.ReflectGetAttributes(_type);
1511                     Type baseType = _type.BaseType;
1512
1513                     while (baseType != null && baseType != typeof(object))
1514                     {
1515                         Attribute[] baseArray = ReflectTypeDescriptionProvider.ReflectGetAttributes(baseType);
1516                         Attribute[] temp = new Attribute[attrArray.Length + baseArray.Length];
1517                         Array.Copy(attrArray, 0, temp, 0, attrArray.Length);
1518                         Array.Copy(baseArray, 0, temp, attrArray.Length, baseArray.Length);
1519                         attrArray = temp;
1520                         baseType = baseType.BaseType;
1521                     }
1522
1523                     // Next, walk the type's interfaces.  We append these to
1524                     // the attribute array as well.
1525                     //
1526                     int ifaceStartIdx = attrArray.Length;
1527                     Type[] interfaces = _type.GetInterfaces(); 
1528                     TypeDescriptor.Trace("Attributes : Walking {0} interfaces", interfaces.Length);
1529                     for(int idx = 0; idx < interfaces.Length; idx++)
1530                     {
1531                         Type iface = interfaces[idx];
1532
1533                         // only do this for public interfaces.
1534                         //
1535                         if ((iface.Attributes & (TypeAttributes.Public | TypeAttributes.NestedPublic)) != 0) {
1536                             // No need to pass an instance into GetTypeDescriptor here because, if someone provided a custom
1537                             // provider based on object, it already would have hit.
1538                             AttributeCollection ifaceAttrs = TypeDescriptor.GetAttributes(iface);
1539                             if (ifaceAttrs.Count > 0) {
1540                                 Attribute[] temp = new Attribute[attrArray.Length + ifaceAttrs.Count];
1541                                 Array.Copy(attrArray, 0, temp, 0, attrArray.Length);
1542                                 ifaceAttrs.CopyTo(temp, attrArray.Length);
1543                                 attrArray = temp;
1544                             }
1545                         }
1546                     }
1547
1548                     // Finally, put all these attributes in a dictionary and filter out the duplicates.
1549                     //
1550                     OrderedDictionary attrDictionary = new OrderedDictionary(attrArray.Length);
1551
1552                     for (int idx = 0; idx < attrArray.Length; idx++)
1553                     {
1554                         bool addAttr = true;
1555                         if (idx >= ifaceStartIdx) {
1556                             for (int ifaceSkipIdx = 0; ifaceSkipIdx < _skipInterfaceAttributeList.Length; ifaceSkipIdx++)
1557                             {
1558                                 if (_skipInterfaceAttributeList[ifaceSkipIdx].IsInstanceOfType(attrArray[idx]))
1559                                 {
1560                                     addAttr = false;
1561                                     break;
1562                                 }
1563                             }
1564
1565                         }
1566
1567                         if (addAttr && !attrDictionary.Contains(attrArray[idx].TypeId)) {
1568                             attrDictionary[attrArray[idx].TypeId] = attrArray[idx];
1569                         }
1570                     }
1571
1572                     attrArray = new Attribute[attrDictionary.Count];
1573                     attrDictionary.Values.CopyTo(attrArray, 0);
1574                     _attributes = new AttributeCollection(attrArray);
1575                 }
1576
1577                 return _attributes;
1578             }
1579
1580             /// <devdoc>
1581             ///     Retrieves the class name for our type.
1582             /// </devdoc>
1583             internal string GetClassName(object instance)
1584             {
1585                 return _type.FullName;
1586             }
1587
1588             /// <devdoc>
1589             ///     Retrieves the component name from the site.
1590             /// </devdoc>
1591             internal string GetComponentName(object instance)
1592             {
1593                 IComponent comp = instance as IComponent;
1594                 if (comp != null) 
1595                 {
1596                     ISite site = comp.Site;
1597                     if (site != null) 
1598                     {
1599                         INestedSite nestedSite = site as INestedSite;
1600                         if (nestedSite != null) 
1601                         {
1602                             return nestedSite.FullName;
1603                         }
1604                         else 
1605                         {
1606                             return site.Name;
1607                         }
1608                     }
1609                 }
1610
1611                 return null;
1612             }
1613
1614             /// <devdoc>
1615             ///     Retrieves the type converter.  If instance is non-null,
1616             ///     it will be used to retrieve attributes.  Otherwise, _type
1617             ///     will be used.
1618             /// </devdoc>
1619             internal TypeConverter GetConverter(object instance)
1620             {
1621                 TypeConverterAttribute typeAttr = null;
1622
1623                 // For instances, the design time object for them may want to redefine the
1624                 // attributes.  So, we search the attribute here based on the instance.  If found,
1625                 // we then search on the same attribute based on type.  If the two don't match, then
1626                 // we cannot cache the value and must re-create every time.  It is rare for a designer
1627                 // to override these attributes, so we want to be smart here.
1628                 //
1629                 if (instance != null)
1630                 {
1631                     typeAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(_type)[typeof(TypeConverterAttribute)];
1632                     TypeConverterAttribute instanceAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(instance)[typeof(TypeConverterAttribute)];
1633                     if (typeAttr != instanceAttr)
1634                     {
1635                         Type converterType = GetTypeFromName(instanceAttr.ConverterTypeName);
1636                         if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) 
1637                         {
1638 #if MONO_FEATURE_CAS
1639                             try {
1640                                 IntSecurity.FullReflection.Assert();
1641 #endif
1642                                 return (TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type);
1643 #if MONO_FEATURE_CAS
1644                             } finally {
1645                                 CodeAccessPermission.RevertAssert();
1646                             }
1647 #endif
1648                         }
1649                     }
1650                 }
1651
1652                 // If we got here, we return our type-based converter.
1653                 //
1654                 if (_converter == null)
1655                 {
1656                     TypeDescriptor.Trace("Converters : Building converter for {0}", _type.Name);
1657
1658                     if (typeAttr == null)
1659                     {
1660                         typeAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(_type)[typeof(TypeConverterAttribute)];
1661                     }
1662
1663                     if (typeAttr != null)
1664                     {
1665                         Type converterType = GetTypeFromName(typeAttr.ConverterTypeName);
1666                         if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) 
1667                         {
1668 #if MONO_FEATURE_CAS
1669                             try {
1670                                 IntSecurity.FullReflection.Assert();
1671 #endif
1672                                 _converter = (TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type);
1673 #if MONO_FEATURE_CAS
1674                             } finally {
1675                                 CodeAccessPermission.RevertAssert();
1676                             }
1677 #endif
1678                         }
1679                     }
1680
1681                     if (_converter == null)
1682                     {
1683                         // We did not get a converter.  Traverse up the base class chain until
1684                         // we find one in the stock hashtable.
1685                         //
1686                         _converter = (TypeConverter)ReflectTypeDescriptionProvider.SearchIntrinsicTable(IntrinsicTypeConverters, _type);
1687                         Debug.Assert(_converter != null, "There is no intrinsic setup in the hashtable for the Object type");
1688                     }
1689                 }
1690
1691                 return _converter;
1692             }
1693
1694             /// <devdoc>
1695             ///     Return the default event. The default event is determined by the
1696             ///     presence of a DefaultEventAttribute on the class.
1697             /// </devdoc>
1698             internal EventDescriptor GetDefaultEvent(object instance)
1699             {
1700                 AttributeCollection attributes;
1701
1702                 if (instance != null)
1703                 {
1704                     attributes = TypeDescriptor.GetAttributes(instance);
1705                 }
1706                 else
1707                 {
1708                     attributes = TypeDescriptor.GetAttributes(_type);
1709                 }
1710
1711                 DefaultEventAttribute attr = (DefaultEventAttribute)attributes[typeof(DefaultEventAttribute)];
1712                 if (attr != null && attr.Name != null)
1713                 {
1714                     if (instance != null)
1715                     {
1716                         return TypeDescriptor.GetEvents(instance)[attr.Name];
1717                     }
1718                     else
1719                     {
1720                         return TypeDescriptor.GetEvents(_type)[attr.Name];
1721                     }
1722                 }
1723
1724                 return null;
1725             }
1726
1727             /// <devdoc>
1728             ///     Return the default property.
1729             /// </devdoc>
1730             internal PropertyDescriptor GetDefaultProperty(object instance)
1731             {
1732                 AttributeCollection attributes;
1733
1734                 if (instance != null)
1735                 {
1736                     attributes = TypeDescriptor.GetAttributes(instance);
1737                 }
1738                 else
1739                 {
1740                     attributes = TypeDescriptor.GetAttributes(_type);
1741                 }
1742
1743                 DefaultPropertyAttribute attr = (DefaultPropertyAttribute)attributes[typeof(DefaultPropertyAttribute)];
1744                 if (attr != null && attr.Name != null)
1745                 {
1746                     if (instance != null)
1747                     {
1748                         return TypeDescriptor.GetProperties(instance)[attr.Name];
1749                     }
1750                     else
1751                     {
1752                         return TypeDescriptor.GetProperties(_type)[attr.Name];
1753                     }
1754                 }
1755
1756                 return null;
1757             }
1758
1759             /// <devdoc>
1760             ///     Retrieves the editor for the given base type.
1761             /// </devdoc>
1762             internal object GetEditor(object instance, Type editorBaseType)
1763             {
1764                 EditorAttribute typeAttr;
1765
1766                 // For instances, the design time object for them may want to redefine the
1767                 // attributes.  So, we search the attribute here based on the instance.  If found,
1768                 // we then search on the same attribute based on type.  If the two don't match, then
1769                 // we cannot cache the value and must re-create every time.  It is rare for a designer
1770                 // to override these attributes, so we want to be smart here.
1771                 //
1772                 if (instance != null)
1773                 {
1774                     typeAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(_type), editorBaseType);
1775                     EditorAttribute instanceAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(instance), editorBaseType);
1776                     if (typeAttr != instanceAttr)
1777                     {
1778                         Type editorType = GetTypeFromName(instanceAttr.EditorTypeName);
1779                         if (editorType != null && editorBaseType.IsAssignableFrom(editorType)) 
1780                         {
1781                             return ReflectTypeDescriptionProvider.CreateInstance(editorType, _type);
1782                         }
1783                     }
1784                 }
1785
1786                 // If we got here, we return our type-based editor.
1787                 //
1788                 lock(this)
1789                 {
1790                     for (int idx = 0; idx < _editorCount; idx++)
1791                     {
1792                         if (_editorTypes[idx] == editorBaseType)
1793                         {
1794                             return _editors[idx];
1795                         }
1796                     }
1797                 }
1798
1799                 // Editor is not cached yet.  Look in the attributes.
1800                 //
1801                 object editor = null;
1802
1803                 typeAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(_type), editorBaseType);
1804                 if (typeAttr != null)
1805                 {
1806                     Type editorType = GetTypeFromName(typeAttr.EditorTypeName);
1807                     if (editorType != null && editorBaseType.IsAssignableFrom(editorType)) 
1808                     {
1809                         editor = ReflectTypeDescriptionProvider.CreateInstance(editorType, _type);
1810                     }
1811                 }
1812
1813                 // Editor is not in the attributes.  Search intrinsic tables.
1814                 //
1815                 if (editor == null)
1816                 {
1817                     Hashtable intrinsicEditors = ReflectTypeDescriptionProvider.GetEditorTable(editorBaseType);
1818                     if (intrinsicEditors != null) 
1819                     {
1820                         editor = ReflectTypeDescriptionProvider.SearchIntrinsicTable(intrinsicEditors, _type);
1821                     }
1822
1823                     // As a quick sanity check, check to see that the editor we got back is of 
1824                     // the correct type.
1825                     //
1826                     if (editor != null && !editorBaseType.IsInstanceOfType(editor)) {
1827                         Debug.Fail("Editor " + editor.GetType().FullName + " is not an instance of " + editorBaseType.FullName + " but it is in that base types table.");
1828                         editor = null;
1829                     }
1830                 }
1831
1832                 if (editor != null)
1833                 {
1834                     lock(this)
1835                     {
1836                         if (_editorTypes == null || _editorTypes.Length == _editorCount)
1837                         {
1838                             int newLength = (_editorTypes == null ? 4 : _editorTypes.Length * 2);
1839
1840                             Type[] newTypes = new Type[newLength];
1841                             object[] newEditors = new object[newLength];
1842
1843                             if (_editorTypes != null)
1844                             {
1845                                 _editorTypes.CopyTo(newTypes, 0);
1846                                 _editors.CopyTo(newEditors, 0);
1847                             }
1848
1849                             _editorTypes = newTypes;
1850                             _editors = newEditors;
1851
1852                             _editorTypes[_editorCount] = editorBaseType;
1853                             _editors[_editorCount++] = editor;
1854                         }
1855                     }
1856                 }
1857
1858                 return editor;
1859             }
1860
1861             /// <devdoc>
1862             ///     Helper method to return an editor attribute of the correct base type.
1863             /// </devdoc>
1864             private static EditorAttribute GetEditorAttribute(AttributeCollection attributes, Type editorBaseType)
1865             {
1866                 foreach(Attribute attr in attributes)
1867                 {
1868                     EditorAttribute edAttr = attr as EditorAttribute;
1869                     if (edAttr != null)
1870                     {
1871                         Type attrEditorBaseType = Type.GetType(edAttr.EditorBaseTypeName);
1872
1873                         if (attrEditorBaseType != null && attrEditorBaseType == editorBaseType) 
1874                         {
1875                             return edAttr;
1876                         }
1877                     }
1878                 }
1879
1880                 return null;
1881             }
1882         
1883             /// <devdoc>
1884             ///     Retrieves the events for this type.
1885             /// </devdoc>
1886             internal EventDescriptorCollection GetEvents()
1887             {
1888                 // Worst case collision scenario:  we don't want the perf hit
1889                 // of taking a lock, so if we collide we will query for
1890                 // events twice.  Not a big deal.
1891                 //
1892                 if (_events == null)
1893                 {
1894                     TypeDescriptor.Trace("Events : Building collection for {0}", _type.Name);
1895
1896                     EventDescriptor[] eventArray;
1897                     Dictionary<string, EventDescriptor> eventList = new Dictionary<string, EventDescriptor>(16);
1898                     Type baseType = _type;
1899                     Type objType = typeof(object);
1900
1901                     do {
1902                         eventArray = ReflectGetEvents(baseType);
1903                         foreach(EventDescriptor ed in eventArray) {
1904                             if (!eventList.ContainsKey(ed.Name)) {
1905                                 eventList.Add(ed.Name, ed);
1906                             }    
1907                         }
1908                         baseType = baseType.BaseType;
1909                     }
1910                     while(baseType != null && baseType != objType);
1911
1912                     eventArray = new EventDescriptor[eventList.Count];
1913                     eventList.Values.CopyTo(eventArray, 0);
1914                     _events = new EventDescriptorCollection(eventArray, true);
1915                 }
1916
1917                 return _events;
1918             }
1919         
1920             /// <devdoc>
1921             ///     Retrieves the properties for this type.
1922             /// </devdoc>
1923             internal PropertyDescriptorCollection GetProperties()
1924             {
1925                 // Worst case collision scenario:  we don't want the perf hit
1926                 // of taking a lock, so if we collide we will query for
1927                 // properties twice.  Not a big deal.
1928                 //
1929                 if (_properties == null)
1930                 {
1931                     TypeDescriptor.Trace("Properties : Building collection for {0}", _type.Name);
1932
1933                     PropertyDescriptor[] propertyArray;
1934                     Dictionary<string, PropertyDescriptor> propertyList = new Dictionary<string, PropertyDescriptor>(10);
1935                     Type baseType = _type;
1936                     Type objType = typeof(object);
1937
1938                     do {
1939                         propertyArray = ReflectGetProperties(baseType);
1940                         foreach(PropertyDescriptor p in propertyArray) {
1941                             if (!propertyList.ContainsKey(p.Name)) {
1942                                 propertyList.Add(p.Name, p);
1943                             }    
1944                         }
1945                         baseType = baseType.BaseType;
1946                     }
1947                     while(baseType != null && baseType != objType);
1948
1949                     propertyArray = new PropertyDescriptor[propertyList.Count];
1950                     propertyList.Values.CopyTo(propertyArray, 0);
1951                     _properties = new PropertyDescriptorCollection(propertyArray, true);
1952                 }
1953
1954                 return _properties;
1955             }
1956         
1957             /// <devdoc>
1958             ///     Retrieves a type from a name.  The Assembly of the type
1959             ///     that this PropertyDescriptor came from is first checked,
1960             ///     then a global Type.GetType is performed.
1961             /// </devdoc>
1962             private Type GetTypeFromName(string typeName) 
1963             {
1964
1965                 if (typeName == null || typeName.Length == 0) 
1966                 {
1967                      return null;
1968                 }
1969
1970                 int commaIndex = typeName.IndexOf(',');
1971                 Type t = null;
1972
1973                 if (commaIndex == -1) 
1974                 {
1975                     t = _type.Assembly.GetType(typeName);
1976                 }
1977
1978                 if (t == null) 
1979                 {
1980                     t = Type.GetType(typeName);
1981                 }
1982
1983                 if (t == null && commaIndex != -1)
1984                 {
1985                     // At design time, it's possible for us to reuse
1986                     // an assembly but add new types.  The app domain
1987                     // will cache the assembly based on identity, however,
1988                     // so it could be looking in the previous version
1989                     // of the assembly and not finding the type.  We work
1990                     // around this by looking for the non-assembly qualified
1991                     // name, which causes the domain to raise a type 
1992                     // resolve event.
1993                     //
1994                     t = Type.GetType(typeName.Substring(0, commaIndex));
1995                 }
1996
1997                 return t;
1998             }
1999
2000             /// <devdoc>
2001             ///     Refreshes the contents of this type descriptor.  This does not
2002             ///     actually requery, but it will clear our state so the next
2003             ///     query re-populates.
2004             /// </devdoc>
2005             internal void Refresh()
2006             {
2007                 _attributes = null;
2008                 _events = null;
2009                 _properties = null;
2010                 _converter = null;
2011                 _editors = null;
2012                 _editorTypes = null;
2013                 _editorCount = 0;
2014             }
2015         }
2016     }
2017 }
2018