New test.
[mono.git] / mcs / class / System / System.ComponentModel / TypeDescriptor.cs
1 //
2 // System.ComponentModel.TypeDescriptor.cs
3 //
4 // Authors:
5 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //
8 // (C) 2002 Ximian, Inc (http://www.ximian.com)
9 // (C) 2003 Andreas Nahr
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System.Collections;
34 using System.Reflection;
35 using System.Globalization;
36 using System.ComponentModel.Design;
37 using System.Security.Permissions;
38
39 namespace System.ComponentModel
40 {
41
42 public sealed class TypeDescriptor
43 {
44         private static readonly object creatingDefaultConverters = new object ();
45         private static Hashtable defaultConverters;
46         private static IComNativeDescriptorHandler descriptorHandler;
47         private static Hashtable componentTable = new Hashtable ();
48         private static Hashtable typeTable = new Hashtable ();
49
50         private TypeDescriptor ()
51         {
52         }
53
54         [MonoTODO]
55         public static void AddEditorTable (Type editorBaseType, Hashtable table)
56         {
57                 throw new NotImplementedException ();
58         }
59
60         public static IDesigner CreateDesigner(IComponent component, Type designerBaseType)
61         {
62                 string tn = designerBaseType.AssemblyQualifiedName;
63                 AttributeCollection col = GetAttributes (component);
64                 
65                 foreach (Attribute at in col) {
66                         DesignerAttribute dat = at as DesignerAttribute;
67                         if (dat != null && tn == dat.DesignerBaseTypeName) {
68                                 return (IDesigner) Activator.CreateInstance (GetTypeFromName (component, dat.DesignerTypeName));
69                         }
70                 }
71                                 
72                 return null;
73         }
74
75         [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
76         public static EventDescriptor CreateEvent (Type componentType,
77                                                    string name,
78                                                    Type type,
79                                                    Attribute [] attributes)
80         {
81                 return new ReflectionEventDescriptor (componentType, name, type, attributes);
82         }
83
84         [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
85         public static EventDescriptor CreateEvent (Type componentType,
86                                                    EventDescriptor oldEventDescriptor,
87                                                    Attribute [] attributes)
88         {
89                 return new ReflectionEventDescriptor (componentType, oldEventDescriptor, attributes);
90         }
91
92         [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
93         public static PropertyDescriptor CreateProperty (Type componentType,
94                                                          string name,
95                                                          Type type,
96                                                          Attribute [] attributes)
97         {
98                 return new ReflectionPropertyDescriptor (componentType, name, type, attributes);
99         }
100
101         [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
102         public static PropertyDescriptor CreateProperty (Type componentType,
103                                                          PropertyDescriptor oldPropertyDescriptor,
104                                                          Attribute [] attributes)
105         {
106                 return new ReflectionPropertyDescriptor (componentType, oldPropertyDescriptor, attributes);
107         }
108
109         public static AttributeCollection GetAttributes (Type componentType)
110         {
111                 if (componentType == null)
112                         return AttributeCollection.Empty;
113
114                 return GetTypeInfo (componentType).GetAttributes ();
115         }
116
117         public static AttributeCollection GetAttributes (object component)
118         {
119                 return GetAttributes (component, false);
120         }
121
122         public static AttributeCollection GetAttributes (object component, bool noCustomTypeDesc)
123         {
124                 if (component == null)
125                     return AttributeCollection.Empty;
126
127                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
128                     return ((ICustomTypeDescriptor) component).GetAttributes ();
129                 } else {
130                         IComponent com = component as IComponent;
131                         if (com != null && com.Site != null)
132                                 return GetComponentInfo (com).GetAttributes ();
133                         else
134                                 return GetTypeInfo (component.GetType()).GetAttributes ();
135                 }
136         }
137
138         public static string GetClassName (object component)
139         {
140                 return GetClassName (component, false);
141         }
142
143         public static string GetClassName (object component, bool noCustomTypeDesc)
144         {
145                 if (component == null)
146                     throw new ArgumentNullException ("component", "component cannot be null");
147
148                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
149                     String res = ((ICustomTypeDescriptor) component).GetClassName ();
150                         if (res == null)
151                                 res = ((ICustomTypeDescriptor) component).GetComponentName ();
152                         if (res == null)
153                                 res = component.GetType ().FullName;
154                         return res;
155                 } else {
156                     return component.GetType ().FullName;
157                 }
158         }
159
160         public static string GetComponentName (object component)
161         {
162                 return GetComponentName (component, false);
163         }
164
165         public static string GetComponentName (object component, bool noCustomTypeDesc)
166         {
167                 if (component == null)
168                     throw new ArgumentNullException ("component", "component cannot be null");
169
170                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
171                     return ((ICustomTypeDescriptor) component).GetComponentName ();
172                 } else {
173                         IComponent c = component as IComponent;
174                         if (c != null && c.Site != null)
175                                 return c.Site.Name;
176 #if NET_2_0
177                         return null;
178 #else
179                         return component.GetType().Name;
180 #endif
181                 }
182         }
183
184         public static TypeConverter GetConverter (object component)
185         {
186                 return GetConverter (component, false);
187         }
188
189         public static TypeConverter GetConverter (object component, bool noCustomTypeDesc)
190         {
191                 if (component == null)
192                         throw new ArgumentNullException ("component", "component cannot be null");
193
194                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
195                         return ((ICustomTypeDescriptor) component).GetConverter ();
196                 } 
197                 else {
198                         Type t = null;
199                         AttributeCollection atts = GetAttributes (component, false);
200                         TypeConverterAttribute tca = (TypeConverterAttribute) atts[typeof(TypeConverterAttribute)];
201                         if (tca != null && tca.ConverterTypeName.Length > 0) {
202                                 t = GetTypeFromName (component as IComponent, tca.ConverterTypeName);
203                         }
204                         
205                         if (t != null) {
206                                 ConstructorInfo ci = t.GetConstructor (new Type[] { typeof(Type) });
207                                 if (ci != null)
208                                         return (TypeConverter) ci.Invoke (new object[] { component.GetType () });
209                                 else
210                                         return (TypeConverter) Activator.CreateInstance (t);
211                         }
212                         else
213                                 return GetConverter (component.GetType ());
214                 }
215         }
216
217         private static Hashtable DefaultConverters
218         {
219                 get {
220                         lock (creatingDefaultConverters) {
221                                 if (defaultConverters != null)
222                                         return defaultConverters;
223                                 
224                                 defaultConverters = new Hashtable ();
225                                 defaultConverters.Add (typeof (bool), typeof (BooleanConverter));
226                                 defaultConverters.Add (typeof (byte), typeof (ByteConverter));
227                                 defaultConverters.Add (typeof (sbyte), typeof (SByteConverter));
228                                 defaultConverters.Add (typeof (string), typeof (StringConverter));
229                                 defaultConverters.Add (typeof (char), typeof (CharConverter));
230                                 defaultConverters.Add (typeof (short), typeof (Int16Converter));
231                                 defaultConverters.Add (typeof (int), typeof (Int32Converter));
232                                 defaultConverters.Add (typeof (long), typeof (Int64Converter));
233                                 defaultConverters.Add (typeof (ushort), typeof (UInt16Converter));
234                                 defaultConverters.Add (typeof (uint), typeof (UInt32Converter));
235                                 defaultConverters.Add (typeof (ulong), typeof (UInt64Converter));
236                                 defaultConverters.Add (typeof (float), typeof (SingleConverter));
237                                 defaultConverters.Add (typeof (double), typeof (DoubleConverter));
238                                 defaultConverters.Add (typeof (decimal), typeof (DecimalConverter));
239                                 defaultConverters.Add (typeof (object), typeof (TypeConverter));
240                                 defaultConverters.Add (typeof (void), typeof (TypeConverter));
241                                 defaultConverters.Add (typeof (Array), typeof (ArrayConverter));
242                                 defaultConverters.Add (typeof (CultureInfo), typeof (CultureInfoConverter));
243                                 defaultConverters.Add (typeof (DateTime), typeof (DateTimeConverter));
244                                 defaultConverters.Add (typeof (Guid), typeof (GuidConverter));
245                                 defaultConverters.Add (typeof (TimeSpan), typeof (TimeSpanConverter));
246                                 defaultConverters.Add (typeof (ICollection), typeof (CollectionConverter));
247                         }
248                         return defaultConverters;
249                 }
250         }
251         
252         public static TypeConverter GetConverter (Type type)
253         {
254                 TypeConverterAttribute tca = null;
255                 Type t = null;
256                 object [] atts = type.GetCustomAttributes (typeof(TypeConverterAttribute), true);
257                 
258                 if (atts.Length > 0)
259                         tca = (TypeConverterAttribute)atts[0];
260                 
261                 if (tca != null) {
262                         t = GetTypeFromName (null, tca.ConverterTypeName);
263                 }
264                 
265                 if (t == null) {
266                         if (type.IsEnum) {
267                                 // EnumConverter needs to know the enum type
268                                 return new EnumConverter(type);
269                         } else if (type.IsArray) {
270                                 return new ArrayConverter ();
271                         }
272                 }
273                 
274                 if (t == null)
275                         t = FindConverterType (type);
276
277                 if (t != null) {
278                         Exception exc = null;
279                         try {
280                                 return (TypeConverter) Activator.CreateInstance (t);
281                         } catch (MissingMethodException e) {
282                                 exc = e;
283                         }
284
285                         try {
286                                 return (TypeConverter) Activator.CreateInstance (t, new object [] {type});
287                         } catch (MissingMethodException e) {
288                                 throw exc;
289                         }
290                 }
291
292                 return new ReferenceConverter (type);    // Default?
293         }
294
295         private static Type FindConverterType (Type type)
296         {
297                 Type t = null;
298                 
299                 // Is there a default converter
300                 t = (Type) DefaultConverters [type];
301                 if (t != null)
302                         return t;
303                 
304                 // Find default converter with a type this type is assignable to
305                 foreach (Type defType in DefaultConverters.Keys) {
306                         if (defType.IsInterface && defType.IsAssignableFrom (type)) {
307                                 return (Type) DefaultConverters [defType];
308                         }
309                 }
310                 
311                 // Nothing found, try the same with our base type
312                 if (type.BaseType != null)
313                         return FindConverterType (type.BaseType);
314                 else
315                         return null;
316         }
317
318         public static EventDescriptor GetDefaultEvent (Type componentType)
319         {
320                 return GetTypeInfo (componentType).GetDefaultEvent ();
321         }
322
323         public static EventDescriptor GetDefaultEvent (object component)
324         {
325                 return GetDefaultEvent (component, false);
326         }
327
328         public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
329         {
330                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
331                         return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
332                 else {
333                         IComponent com = component as IComponent;
334                         if (com != null && com.Site != null)
335                                 return GetComponentInfo (com).GetDefaultEvent ();
336                         else
337                                 return GetTypeInfo (component.GetType()).GetDefaultEvent ();
338                 }
339         }
340
341         public static PropertyDescriptor GetDefaultProperty (Type componentType)
342         {
343                 return GetTypeInfo (componentType).GetDefaultProperty ();
344         }
345
346         public static PropertyDescriptor GetDefaultProperty (object component)
347         {
348                 return GetDefaultProperty (component, false);
349         }
350
351         public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
352         {
353                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
354                         return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
355                 else {
356                         IComponent com = component as IComponent;
357                         if (com != null && com.Site != null)
358                                 return GetComponentInfo (com).GetDefaultProperty ();
359                         else
360                                 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
361                 }
362         }
363
364         public static object GetEditor (Type componentType, Type editorBaseType)
365         {
366                 Type t = null;
367                 object [] atts = componentType.GetCustomAttributes (typeof(EditorAttribute), true);
368                 if (atts == null || atts.Length == 0)
369                         return null;
370                 
371                 
372                 foreach (EditorAttribute ea in atts)
373                 {
374                         t = GetTypeFromName (null, ea.EditorTypeName);
375                         if (t.IsSubclassOf(editorBaseType))
376                                 break;
377                 }
378
379                 if (t != null) {
380                         Exception exc = null;
381                         try {
382                                 return Activator.CreateInstance (t);
383                         } catch (MissingMethodException e) {
384                                 exc = e;
385                         }
386
387                         try {
388                                 return Activator.CreateInstance (t, new object [] {componentType});
389                         } catch (MissingMethodException e) {
390                                 throw exc;
391                         }
392                 }
393
394                 return null;    // No editor specified
395         }
396
397         public static object GetEditor (object component, Type editorBaseType)
398         {
399                 return GetEditor (component, editorBaseType, false);
400         }
401
402         public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
403         {
404                 if (component == null)
405                         throw new ArgumentNullException ("component");
406                 if (editorBaseType == null)
407                         throw new ArgumentNullException ("editorBaseType");
408                 
409                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
410                         return ((ICustomTypeDescriptor) component).GetEditor (editorBaseType);
411
412                 object [] atts = component.GetType ().GetCustomAttributes (typeof (EditorAttribute), true);
413                 if (atts.Length == 0)
414                         return null;
415                 string target = editorBaseType.AssemblyQualifiedName;
416                 
417                 foreach (EditorAttribute ea in atts){
418                         if (ea.EditorBaseTypeName == target){
419                                 Type t = Type.GetType (ea.EditorTypeName, true);
420
421                                 return Activator.CreateInstance (t);
422                         }
423                 }
424                 return null;
425         }
426
427         public static EventDescriptorCollection GetEvents (object component)
428         {
429                 return GetEvents (component, false);
430         }
431
432         public static EventDescriptorCollection GetEvents (Type componentType)
433         {
434                 return GetEvents (componentType, null);
435         }
436
437         public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes)
438         {
439                 return GetEvents (component, attributes, false);
440         }
441
442         public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
443         {
444                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
445                         return ((ICustomTypeDescriptor) component).GetEvents ();
446                 else {
447                         IComponent com = component as IComponent;
448                         if (com != null && com.Site != null)
449                                 return GetComponentInfo (com).GetEvents ();
450                         else
451                                 return GetTypeInfo (component.GetType()).GetEvents ();
452                 }
453         }
454
455         public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
456         {
457                 return GetTypeInfo (componentType).GetEvents (attributes);
458         }
459
460         public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
461         {
462                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
463                         return ((ICustomTypeDescriptor) component).GetEvents (attributes);
464                 else {
465                         IComponent com = component as IComponent;
466                         if (com != null && com.Site != null)
467                                 return GetComponentInfo (com).GetEvents (attributes);
468                         else
469                                 return GetTypeInfo (component.GetType()).GetEvents (attributes);
470                 }
471         }
472
473         public static PropertyDescriptorCollection GetProperties (object component)
474         {
475                 return GetProperties (component, false);
476         }
477
478         public static PropertyDescriptorCollection GetProperties (Type componentType)
479         {
480                 return GetProperties (componentType, null);
481         }
482
483         public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes)
484         {
485                 return GetProperties (component, attributes, false);
486         }
487
488         public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
489         {
490                 if (component == null)
491                         return PropertyDescriptorCollection.Empty;
492
493                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
494                         return ((ICustomTypeDescriptor) component).GetProperties (attributes);
495                 else {
496                         IComponent com = component as IComponent;
497                         if (com != null && com.Site != null)
498                                 return GetComponentInfo (com).GetProperties (attributes);
499                         else
500                                 return GetTypeInfo (component.GetType()).GetProperties (attributes);
501                 }
502         }
503
504         public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
505         {
506                 if (component == null)
507                         return PropertyDescriptorCollection.Empty;
508
509                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
510                         return ((ICustomTypeDescriptor) component).GetProperties ();
511                 else {
512                         IComponent com = component as IComponent;
513                         if (com != null && com.Site != null)
514                                 return GetComponentInfo (com).GetProperties ();
515                         else
516                                 return GetTypeInfo (component.GetType()).GetProperties ();
517                 }
518         }
519
520         public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
521         {
522                 return GetTypeInfo (componentType).GetProperties (attributes);
523         }
524
525         public static void SortDescriptorArray (IList infos)
526         {
527                 string[] names = new string [infos.Count];
528                 object[] values = new object [infos.Count];
529                 for (int n=0; n<names.Length; n++) {
530                         names[n] = ((MemberDescriptor)infos[n]).Name;
531                         values[n] = infos[n];
532                 }
533                 Array.Sort (names, values);
534                 infos.Clear();
535                 foreach (object ob in values)
536                         infos.Add (ob);
537         }
538
539         public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
540                 [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
541                 get { return descriptorHandler; }
542                 [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
543                 set { descriptorHandler = value; }
544         }
545
546         public static void Refresh (Assembly assembly)
547         {
548                 foreach (Type type in assembly.GetTypes())
549                         Refresh (type);
550         }
551
552         public static void Refresh (Module module)
553         {
554                 foreach (Type type in module.GetTypes())
555                         Refresh (type);
556         }
557
558         public static void Refresh (object component)
559         {
560                 lock (componentTable)
561                 {
562                         componentTable.Remove (component);
563                 }
564                 if (Refreshed != null) Refreshed (new RefreshEventArgs (component));
565         }
566
567         public static void Refresh (Type type)
568         {
569                 lock (typeTable)
570                 {
571                         typeTable.Remove (type);
572                 }
573                 if (Refreshed != null) Refreshed (new RefreshEventArgs (type));
574         }
575
576         static EventHandler onDispose;
577
578         static void OnComponentDisposed (object sender, EventArgs args)
579         {
580                 lock (componentTable) {
581                         componentTable.Remove (sender);
582                 }
583         }
584
585         public static event RefreshEventHandler Refreshed;
586         
587         internal static ComponentInfo GetComponentInfo (IComponent com)
588         {
589                 lock (componentTable)
590                 {
591                         ComponentInfo ci = (ComponentInfo) componentTable [com];
592                         if (ci == null) {
593                                 if (onDispose == null)
594                                         onDispose = new EventHandler (OnComponentDisposed);
595
596                                 com.Disposed += onDispose;
597                                 ci = new ComponentInfo (com);
598                                 componentTable [com] = ci;
599                         }
600                         return ci;
601                 }
602         }
603         
604         internal static TypeInfo GetTypeInfo (Type type)
605         {
606                 lock (typeTable)
607                 {
608                         TypeInfo ci = (TypeInfo) typeTable [type];
609                         if (ci == null) {
610                                 ci = new TypeInfo (type);
611                                 typeTable [type] = ci;
612                         }
613                         return ci;
614                 }
615         }
616         
617         static Type GetTypeFromName (IComponent component, string typeName)
618         {
619                 if (component != null && component.Site != null) {
620                         ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
621                         if (resver != null)
622                                 return resver.GetType (typeName, true, false);
623                 }
624                 
625                 Type t = Type.GetType (typeName);
626                 if (t == null) throw new ArgumentException ("Type '" + typeName + "' not found");
627                 return t;
628         }
629 }
630
631         internal abstract class Info
632         {
633                 Type _infoType;
634                 EventDescriptor _defaultEvent;
635                 bool _gotDefaultEvent;
636                 PropertyDescriptor _defaultProperty;
637                 bool _gotDefaultProperty;
638                 AttributeCollection _attributes;
639                 
640                 public Info (Type infoType)
641                 {
642                         _infoType = infoType;
643                 }
644                 
645                 public abstract AttributeCollection GetAttributes ();
646                 public abstract EventDescriptorCollection GetEvents ();
647                 public abstract PropertyDescriptorCollection GetProperties ();
648                 
649                 public Type InfoType
650                 {
651                         get { return _infoType; }
652                 }
653                 
654                 public EventDescriptorCollection GetEvents (Attribute[] attributes)
655                 {
656                         EventDescriptorCollection evs = GetEvents ();
657                         if (attributes == null)
658                                 return evs;
659                         else
660                                 return evs.Filter (attributes);
661                 }
662                 
663                 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
664                 {
665                         PropertyDescriptorCollection props = GetProperties ();
666                         if (attributes == null)
667                                 return props;
668                         else
669                                 return props.Filter (attributes);
670                 }
671                 
672                 public EventDescriptor GetDefaultEvent ()
673                 {
674                         if (_gotDefaultEvent)
675                                 return _defaultEvent;
676                         
677                         DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
678                         if (attr == null || attr.Name == null) 
679                                 _defaultEvent = null;
680                         else {
681                                 EventDescriptorCollection events = GetEvents ();
682                                 _defaultEvent = events [attr.Name];
683 #if !NET_2_0
684                                 // In our test case (TypeDescriptorTest.TestGetDefaultEvent), we have
685                                 // a scenario where a custom filter adds the DefaultEventAttribute,
686                                 // but its FilterEvents method removes the event the
687                                 // DefaultEventAttribute applied to.  .NET 1.x accepts this and returns
688                                 // the *other* event defined in the class.
689                                 //
690                                 // Consequently, we know we have a DefaultEvent, but we need to check
691                                 // and ensure that the requested event is unfiltered.  If it is, just
692                                 // grab the first element in the collection.
693                                 if (_defaultEvent == null && events.Count > 0)
694                                         _defaultEvent = events [0];
695 #endif
696                         }
697                         _gotDefaultEvent = true;
698                         return _defaultEvent;
699                 }
700                 
701                 public PropertyDescriptor GetDefaultProperty ()
702                 {
703                         if (_gotDefaultProperty)
704                                 return _defaultProperty;
705                         
706                         DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
707                         if (attr == null || attr.Name == null) 
708                                 _defaultProperty = null;
709                         else {
710                                 PropertyDescriptorCollection properties = GetProperties ();
711                                 _defaultProperty = properties[attr.Name];
712                         }
713                         _gotDefaultProperty = true;
714                         return _defaultProperty;
715                 }
716                 
717                 protected AttributeCollection GetAttributes (IComponent comp)
718                 {
719                         if (_attributes != null)
720                                 return _attributes;
721                         
722                         bool cache = true;
723                         object[] ats = _infoType.GetCustomAttributes (true);
724                         Hashtable t = new Hashtable ();
725
726                         // Filter the custom attributes, so that only the top
727                         // level of the same type are left.
728                         //
729                         for (int i = ats.Length -1; i >= 0; i--) {
730                                 t [((Attribute) ats[i]).TypeId] = ats[i];
731                         }
732                                         
733                         if (comp != null && comp.Site != null) 
734                         {
735                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) comp.Site.GetService (typeof(ITypeDescriptorFilterService));
736                                 cache = filter.FilterAttributes (comp, t);
737                         }
738                         
739                         ArrayList atts = new ArrayList ();
740                         atts.AddRange (t.Values);
741                         AttributeCollection attCol = new AttributeCollection (atts);
742                         if (cache)
743                                 _attributes = attCol;
744                         return attCol;
745                 }
746         }
747
748         internal class ComponentInfo : Info
749         {
750                 IComponent _component;
751                 EventDescriptorCollection _events;
752                 PropertyDescriptorCollection _properties;
753                 
754                 public ComponentInfo (IComponent component): base (component.GetType())
755                 {
756                         _component = component;
757                 }
758                 
759                 public override AttributeCollection GetAttributes ()
760                 {
761                         return base.GetAttributes (_component);
762                 }
763                 
764                 public override EventDescriptorCollection GetEvents ()
765                 {
766                         if (_events != null)
767                                 return _events;
768                         
769                         bool cache = true;
770                         EventInfo[] events = _component.GetType().GetEvents ();
771                         Hashtable t = new Hashtable ();
772                         foreach (EventInfo ev in events)
773                                 t [ev.Name] = new ReflectionEventDescriptor (ev);
774                                         
775                         if (_component.Site != null) 
776                         {
777                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
778                                 cache = filter.FilterEvents (_component, t);
779                         }
780                         
781                         ArrayList atts = new ArrayList ();
782                         atts.AddRange (t.Values);
783                         EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
784                         if (cache) _events = attCol;
785                         return attCol;
786                 }
787                 
788                 public override PropertyDescriptorCollection GetProperties ()
789                 {
790                         if (_properties != null)
791                                 return _properties;
792                         
793                         bool cache = true;
794                         PropertyInfo[] props = _component.GetType().GetProperties (BindingFlags.Instance | BindingFlags.Public);
795                         Hashtable t = new Hashtable ();
796                         foreach (PropertyInfo pr in props)
797                                 t [pr.Name] = new ReflectionPropertyDescriptor (pr);
798                                         
799                         if (_component.Site != null) 
800                         {
801                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
802                                 cache = filter.FilterProperties (_component, t);
803                         }
804
805                         PropertyDescriptor[] descriptors = new PropertyDescriptor[t.Values.Count];
806                         t.Values.CopyTo (descriptors, 0);
807                         PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (descriptors, true);
808                         if (cache)
809                                 _properties = attCol;
810                         return attCol;
811                 }
812         }
813         
814         internal class TypeInfo : Info
815         {
816                 EventDescriptorCollection _events;
817                 PropertyDescriptorCollection _properties;
818                 
819                 public TypeInfo (Type t): base (t)
820                 {
821                 }
822                 
823                 public override AttributeCollection GetAttributes ()
824                 {
825                         return base.GetAttributes (null);
826                 }
827                 
828                 public override EventDescriptorCollection GetEvents ()
829                 {
830                         if (_events != null)
831                                 return _events;
832                         
833                         EventInfo[] events = InfoType.GetEvents ();
834                         EventDescriptor[] descs = new EventDescriptor [events.Length];
835                         for (int n=0; n<events.Length; n++)
836                                 descs [n] = new ReflectionEventDescriptor (events[n]);
837
838                         _events = new EventDescriptorCollection (descs);
839                         return _events;
840                 }
841                 
842                 public override PropertyDescriptorCollection GetProperties ()
843                 {
844                         if (_properties != null)
845                                 return _properties;
846                         
847                         PropertyInfo[] props = InfoType.GetProperties (BindingFlags.Instance | BindingFlags.Public);
848                         ArrayList descs = new ArrayList (props.Length);
849                         for (int n=0; n<props.Length; n++)
850                                 if (props [n].GetIndexParameters ().Length == 0)
851                                         descs.Add (new ReflectionPropertyDescriptor (props[n]));
852
853                         _properties = new PropertyDescriptorCollection ((PropertyDescriptor[]) descs.ToArray (typeof (PropertyDescriptor)), true);
854                         return _properties;
855                 }
856         }
857 }