2005-07-21 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[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;
34 using System.Collections;
35 using System.Reflection;
36 using System.Globalization;
37 using System.ComponentModel.Design;
38
39 namespace System.ComponentModel
40 {
41
42 public sealed class TypeDescriptor
43 {
44         private static readonly string creatingDefaultConverters = "creatingDefaultConverters";
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         public static EventDescriptor CreateEvent (Type componentType,
76                                                    string name,
77                                                    Type type,
78                                                    Attribute [] attributes)
79         {
80                 return new ReflectionEventDescriptor (componentType, name, type, attributes);
81         }
82
83         public static EventDescriptor CreateEvent (Type componentType,
84                                                    EventDescriptor oldEventDescriptor,
85                                                    Attribute [] attributes)
86         {
87                 return new ReflectionEventDescriptor (componentType, oldEventDescriptor, attributes);
88         }
89
90         public static PropertyDescriptor CreateProperty (Type componentType,
91                                                          string name,
92                                                          Type type,
93                                                          Attribute [] attributes)
94         {
95                 return new ReflectionPropertyDescriptor (componentType, name, type, attributes);
96         }
97
98         public static PropertyDescriptor CreateProperty (Type componentType,
99                                                          PropertyDescriptor oldPropertyDescriptor,
100                                                          Attribute [] attributes)
101         {
102                 return new ReflectionPropertyDescriptor (componentType, oldPropertyDescriptor, attributes);
103         }
104
105         public static AttributeCollection GetAttributes (Type componentType)
106         {
107                 if (componentType == null)
108                         return AttributeCollection.Empty;
109
110                 return GetTypeInfo (componentType).GetAttributes ();
111         }
112
113         public static AttributeCollection GetAttributes (object component)
114         {
115                 return GetAttributes (component, false);
116         }
117
118         public static AttributeCollection GetAttributes (object component, bool noCustomTypeDesc)
119         {
120                 if (component == null)
121                     return AttributeCollection.Empty;
122
123                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
124                     return ((ICustomTypeDescriptor) component).GetAttributes ();
125                 } else {
126                         IComponent com = component as IComponent;
127                         if (com != null)
128                                 return GetComponentInfo (com).GetAttributes ();
129                         else
130                                 return GetTypeInfo (component.GetType()).GetAttributes ();
131                 }
132         }
133
134         public static string GetClassName (object component)
135         {
136                 return GetClassName (component, false);
137         }
138
139         public static string GetClassName (object component, bool noCustomTypeDesc)
140         {
141                 if (component == null)
142                     throw new ArgumentNullException ("component", "component cannot be null");
143
144                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
145                     return ((ICustomTypeDescriptor) component).GetClassName ();
146                 } else {
147                     return component.GetType ().FullName;
148                 }
149         }
150
151         public static string GetComponentName (object component)
152         {
153                 return GetComponentName (component, false);
154         }
155
156         public static string GetComponentName (object component, bool noCustomTypeDesc)
157         {
158                 if (component == null)
159                     throw new ArgumentNullException ("component", "component cannot be null");
160
161                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
162                     return ((ICustomTypeDescriptor) component).GetComponentName ();
163                 } else {
164                         IComponent c = component as IComponent;
165                         if (c != null && c.Site != null)
166                                 return c.Site.Name;
167 #if NET_2_0
168                         return null;
169 #else
170
171 #endif
172                         return component.GetType().Name;
173                 }
174         }
175
176         public static TypeConverter GetConverter (object component)
177         {
178                 return GetConverter (component.GetType ());
179         }
180
181         public static TypeConverter GetConverter (object component, bool noCustomTypeDesc)
182         {
183                 if (component == null)
184                         throw new ArgumentNullException ("component", "component cannot be null");
185
186                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
187                         return ((ICustomTypeDescriptor) component).GetConverter ();
188                 } 
189                 else {
190                         Type t = null;
191                         AttributeCollection atts = GetAttributes (component, false);
192                         TypeConverterAttribute tca = (TypeConverterAttribute) atts[typeof(TypeConverterAttribute)];
193                         if (tca != null && tca.ConverterTypeName.Length > 0) {
194                                 t = GetTypeFromName (component as IComponent, tca.ConverterTypeName);
195                         }
196                         
197                         if (t != null) {
198                                 ConstructorInfo ci = t.GetConstructor (new Type[] { typeof(Type) });
199                                 if (ci != null)
200                                         return (TypeConverter) ci.Invoke (new object[] { component.GetType () });
201                                 else
202                                         return (TypeConverter) Activator.CreateInstance (t);
203                         }
204                         else
205                                 return GetConverter (component.GetType ());
206                 }
207         }
208
209         private static Hashtable DefaultConverters
210         {
211                 get {
212                         if (defaultConverters != null)
213                                 return defaultConverters;
214
215                         lock (creatingDefaultConverters) {
216                                 if (defaultConverters != null)
217                                         return defaultConverters;
218                                 
219                                 defaultConverters = new Hashtable ();
220                                 defaultConverters.Add (typeof (bool), typeof (BooleanConverter));
221                                 defaultConverters.Add (typeof (byte), typeof (ByteConverter));
222                                 defaultConverters.Add (typeof (sbyte), typeof (SByteConverter));
223                                 defaultConverters.Add (typeof (string), typeof (StringConverter));
224                                 defaultConverters.Add (typeof (char), typeof (CharConverter));
225                                 defaultConverters.Add (typeof (short), typeof (Int16Converter));
226                                 defaultConverters.Add (typeof (int), typeof (Int32Converter));
227                                 defaultConverters.Add (typeof (long), typeof (Int64Converter));
228                                 defaultConverters.Add (typeof (ushort), typeof (UInt16Converter));
229                                 defaultConverters.Add (typeof (uint), typeof (UInt32Converter));
230                                 defaultConverters.Add (typeof (ulong), typeof (UInt64Converter));
231                                 defaultConverters.Add (typeof (float), typeof (SingleConverter));
232                                 defaultConverters.Add (typeof (double), typeof (DoubleConverter));
233                                 defaultConverters.Add (typeof (decimal), typeof (DecimalConverter));
234                                 defaultConverters.Add (typeof (object), typeof (TypeConverter));
235                                 defaultConverters.Add (typeof (void), typeof (TypeConverter));
236                                 defaultConverters.Add (typeof (Array), typeof (ArrayConverter));
237                                 defaultConverters.Add (typeof (CultureInfo), typeof (CultureInfoConverter));
238                                 defaultConverters.Add (typeof (DateTime), typeof (DateTimeConverter));
239                                 defaultConverters.Add (typeof (Guid), typeof (GuidConverter));
240                                 defaultConverters.Add (typeof (TimeSpan), typeof (TimeSpanConverter));
241                                 defaultConverters.Add (typeof (ICollection), typeof (CollectionConverter));
242                         }
243                         return defaultConverters;
244                 }
245         }
246         
247         public static TypeConverter GetConverter (Type type)
248         {
249                 TypeConverterAttribute tca = null;
250                 Type t = null;
251                 object [] atts = type.GetCustomAttributes (typeof(TypeConverterAttribute), true);
252                 
253                 if (atts.Length > 0)
254                         tca = (TypeConverterAttribute)atts[0];
255                 
256                 if (tca != null) {
257                         t = GetTypeFromName (null, tca.ConverterTypeName);
258                 }
259                 
260                 if (t == null) {
261                         if (type.IsEnum) {
262                                 // EnumConverter needs to know the enum type
263                                 return new EnumConverter(type);
264                         } else if (type.IsArray) {
265                                 return new ArrayConverter ();
266                         }
267                 }
268                 \r
269                 if (t == null)\r
270                         t = FindConverterType (type);\r
271 \r
272                 if (t != null) {
273                         Exception exc = null;
274                         try {
275                                 return (TypeConverter) Activator.CreateInstance (t);
276                         } catch (MissingMethodException e) {
277                                 exc = e;
278                         }
279
280                         try {
281                                 return (TypeConverter) Activator.CreateInstance (t, new object [] {type});
282                         } catch (MissingMethodException e) {
283                                 throw exc;
284                         }
285                 }
286
287                 return new ReferenceConverter (type);    // Default?
288         }\r
289 \r
290         private static Type FindConverterType (Type type)\r
291         {\r
292                 Type t = null;\r
293                 \r
294                 // Is there a default converter\r
295                 t = (Type) DefaultConverters [type];\r
296                 if (t != null)\r
297                         return t;\r
298                 \r
299                 // Find default converter with a type this type is assignable to\r
300                 foreach (Type defType in DefaultConverters.Keys) {\r
301                         if (defType.IsInterface && defType.IsAssignableFrom (type)) {\r
302                                 return (Type) DefaultConverters [defType];\r
303                         }\r
304                 }\r
305                 \r
306                 // Nothing found, try the same with our base type\r
307                 if (type.BaseType != null)\r
308                         return FindConverterType (type.BaseType);\r
309                 else\r
310                         return null;\r
311         }
312
313         public static EventDescriptor GetDefaultEvent (Type componentType)
314         {
315                 return GetTypeInfo (componentType).GetDefaultEvent ();
316         }
317
318         public static EventDescriptor GetDefaultEvent (object component)
319         {
320                 return GetDefaultEvent (component, false);
321         }
322
323         public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
324         {
325                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
326                         return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
327                 else {
328                         IComponent com = component as IComponent;
329                         if (com != null)
330                                 return GetComponentInfo (com).GetDefaultEvent ();
331                         else
332                                 return GetTypeInfo (component.GetType()).GetDefaultEvent ();
333                 }
334         }
335
336         public static PropertyDescriptor GetDefaultProperty (Type componentType)
337         {
338                 return GetTypeInfo (componentType).GetDefaultProperty ();
339         }
340
341         public static PropertyDescriptor GetDefaultProperty (object component)
342         {
343                 return GetDefaultProperty (component, false);
344         }
345
346         public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
347         {
348                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
349                         return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
350                 else {
351                         IComponent com = component as IComponent;
352                         if (com != null)
353                                 return GetComponentInfo (com).GetDefaultProperty ();
354                         else
355                                 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
356                 }
357         }
358
359         public static object GetEditor (Type componentType, Type editorBaseType)
360         {
361                 Type t = null;
362                 object [] atts = componentType.GetCustomAttributes (typeof(EditorAttribute), true);
363                 if (atts == null || atts.Length == 0)
364                         return null;
365                 
366                 
367                 foreach (EditorAttribute ea in atts)
368                 {
369                         t = GetTypeFromName (null, ea.EditorTypeName);
370                         if (t.IsSubclassOf(editorBaseType))
371                                 break;
372                 }
373
374                 if (t != null) {
375                         Exception exc = null;
376                         try {
377                                 return Activator.CreateInstance (t);
378                         } catch (MissingMethodException e) {
379                                 exc = e;
380                         }
381
382                         try {
383                                 return Activator.CreateInstance (t, new object [] {componentType});
384                         } catch (MissingMethodException e) {
385                                 throw exc;
386                         }
387                 }
388
389                 return null;    // No editor specified
390         }
391
392         public static object GetEditor (object component, Type editorBaseType)
393         {
394                 return GetEditor (component, editorBaseType, false);
395         }
396
397         [MonoTODO]
398         public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
399         {
400                 throw new NotImplementedException ();
401         }
402
403         public static EventDescriptorCollection GetEvents (object component)
404         {
405                 return GetEvents (component, false);
406         }
407
408         public static EventDescriptorCollection GetEvents (Type componentType)
409         {
410                 return GetEvents (componentType, null);
411         }
412
413         public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes)
414         {
415                 return GetEvents (component, attributes, false);
416         }
417
418         public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
419         {
420                 return GetEvents (component, null, noCustomTypeDesc);
421         }
422
423         public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
424         {
425                 return GetTypeInfo (componentType).GetEvents (attributes);
426         }
427
428         public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
429         {
430                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
431                         return ((ICustomTypeDescriptor) component).GetEvents (attributes);
432                 else {
433                         IComponent com = component as IComponent;
434                         if (com != null)
435                                 return GetComponentInfo (com).GetEvents (attributes);
436                         else
437                                 return GetTypeInfo (component.GetType()).GetEvents (attributes);
438                 }
439         }
440
441         public static PropertyDescriptorCollection GetProperties (object component)
442         {
443                 return GetProperties (component, false);
444         }
445
446         public static PropertyDescriptorCollection GetProperties (Type componentType)
447         {
448                 return GetProperties (componentType, null);
449         }
450
451         public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes)
452         {
453                 return GetProperties (component, attributes, false);
454         }
455
456         public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
457         {
458                 if (component == null)
459                         throw new ArgumentNullException ("component");
460
461                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
462                         return ((ICustomTypeDescriptor) component).GetProperties (attributes);
463                 else {
464                         IComponent com = component as IComponent;
465                         if (com != null)
466                                 return GetComponentInfo (com).GetProperties (attributes);
467                         else
468                                 return GetTypeInfo (component.GetType()).GetProperties (attributes);
469                 }
470         }
471
472         public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
473         {
474                 return GetProperties (component, null, noCustomTypeDesc);
475         }
476
477         public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
478         {
479                 return GetTypeInfo (componentType).GetProperties (attributes);
480         }
481
482         public static void SortDescriptorArray (IList infos)
483         {
484                 string[] names = new string [infos.Count];
485                 object[] values = new object [infos.Count];
486                 for (int n=0; n<names.Length; n++) {
487                         names[n] = ((MemberDescriptor)infos[n]).Name;
488                         values[n] = infos[n];
489                 }
490                 Array.Sort (names, values);
491                 infos.Clear();
492                 foreach (object ob in values)
493                         infos.Add (ob);
494         }
495
496         public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
497                 get { return descriptorHandler; }
498                 set { descriptorHandler = value; }
499         }
500
501         public static void Refresh (Assembly assembly)
502         {
503                 foreach (Type type in assembly.GetTypes())
504                         Refresh (type);
505         }
506
507         public static void Refresh (Module module)
508         {
509                 foreach (Type type in module.GetTypes())
510                         Refresh (type);
511         }
512
513         public static void Refresh (object component)
514         {
515                 lock (componentTable)
516                 {
517                         componentTable.Remove (component);
518                 }
519                 if (Refreshed != null) Refreshed (new RefreshEventArgs (component));
520         }
521
522         public static void Refresh (Type type)
523         {
524                 lock (typeTable)
525                 {
526                         typeTable.Remove (type);
527                 }
528                 if (Refreshed != null) Refreshed (new RefreshEventArgs (type));
529         }
530
531         static EventHandler onDispose;
532
533         static void OnComponentDisposed (object sender, EventArgs args)
534         {
535                 lock (componentTable) {
536                         componentTable.Remove (sender);
537                 }
538         }
539
540         public static event RefreshEventHandler Refreshed;
541         
542         internal static ComponentInfo GetComponentInfo (IComponent com)
543         {
544                 lock (componentTable)
545                 {
546                         ComponentInfo ci = (ComponentInfo) componentTable [com];
547                         if (ci == null) {
548                                 if (onDispose == null)
549                                         onDispose = new EventHandler (OnComponentDisposed);
550
551                                 com.Disposed += onDispose;
552                                 ci = new ComponentInfo (com);
553                                 componentTable [com] = ci;
554                         }
555                         return ci;
556                 }
557         }
558         
559         internal static TypeInfo GetTypeInfo (Type type)
560         {
561                 lock (typeTable)
562                 {
563                         TypeInfo ci = (TypeInfo) typeTable [type];
564                         if (ci == null) {
565                                 ci = new TypeInfo (type);
566                                 typeTable [type] = ci;
567                         }
568                         return ci;
569                 }
570         }
571         
572         static Type GetTypeFromName (IComponent component, string typeName)
573         {
574                 if (component != null && component.Site != null) {
575                         ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
576                         if (resver != null) return resver.GetType (typeName, true, false);
577                 }
578                 
579                 Type t = Type.GetType (typeName);
580                 if (t == null) throw new ArgumentException ("Type '" + typeName + "' not found");
581                 return t;
582         }
583 }
584
585         internal abstract class Info
586         {
587                 Type _infoType;
588                 EventDescriptor _defaultEvent;
589                 bool _gotDefaultEvent;
590                 PropertyDescriptor _defaultProperty;
591                 bool _gotDefaultProperty;
592                 AttributeCollection _attributes;
593                 
594                 public Info (Type infoType)
595                 {
596                         _infoType = infoType;
597                 }
598                 
599                 public abstract AttributeCollection GetAttributes ();
600                 public abstract EventDescriptorCollection GetEvents ();
601                 public abstract PropertyDescriptorCollection GetProperties ();
602                 
603                 public Type InfoType
604                 {
605                         get { return _infoType; }
606                 }
607                 
608                 public EventDescriptorCollection GetEvents (Attribute[] attributes)
609                 {
610                         EventDescriptorCollection evs = GetEvents ();
611                         if (attributes == null) return evs;
612                         else return evs.Filter (attributes);
613                 }
614                 
615                 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
616                 {
617                         PropertyDescriptorCollection props = GetProperties ();
618                         if (attributes == null) return props;
619                         else return props.Filter (attributes);
620                 }
621                 
622                 public EventDescriptor GetDefaultEvent ()
623                 {
624                         if (_gotDefaultEvent) return _defaultEvent;
625                         
626                         DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
627                         if (attr == null || attr.Name == null) 
628                                 _defaultEvent = null;
629                         else {
630                                 EventDescriptorCollection events = GetEvents ();
631                                 _defaultEvent = events [attr.Name];
632 #if !NET_2_0
633                                 // In our test case (TypeDescriptorTest.TestGetDefaultEvent), we have
634                                 // a scenario where a custom filter adds the DefaultEventAttribute,
635                                 // but its FilterEvents method removes the event the
636                                 // DefaultEventAttribute applied to.  .NET 1.x accepts this and returns
637                                 // the *other* event defined in the class.
638                                 //
639                                 // Consequently, we know we have a DefaultEvent, but we need to check
640                                 // and ensure that the requested event is unfiltered.  If it is, just
641                                 // grab the first element in the collection.
642                                 if (_defaultEvent == null && events.Count > 0)
643                                         _defaultEvent = events [0];
644 #endif
645                         }
646                         _gotDefaultEvent = true;
647                         return _defaultEvent;
648                 }
649                 
650                 public PropertyDescriptor GetDefaultProperty ()
651                 {
652                         if (_gotDefaultProperty) return _defaultProperty;
653                         
654                         DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
655                         if (attr == null || attr.Name == null) 
656                                 _defaultProperty = null;
657                         else {
658                                 PropertyDescriptorCollection properties = GetProperties ();
659                                 _defaultProperty = properties[attr.Name];
660                         }
661                         _gotDefaultProperty = true;
662                         return _defaultProperty;
663                 }
664                 
665                 protected AttributeCollection GetAttributes (IComponent comp)
666                 {
667                         if (_attributes != null) return _attributes;
668                         
669                         bool cache = true;
670                         object[] ats = _infoType.GetCustomAttributes (true);
671                         Hashtable t = new Hashtable ();
672                         foreach (Attribute at in ats)
673                                 t [at.TypeId] = at;
674                                         
675                         if (comp != null && comp.Site != null) 
676                         {
677                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) comp.Site.GetService (typeof(ITypeDescriptorFilterService));
678                                 cache = filter.FilterAttributes (comp, t);
679                         }
680                         
681                         ArrayList atts = new ArrayList ();
682                         atts.AddRange (t.Values);
683                         AttributeCollection attCol = new AttributeCollection (atts);
684                         if (cache) _attributes = attCol;
685                         return attCol;
686                 }
687         }
688
689         internal class ComponentInfo : Info
690         {
691                 IComponent _component;
692                 EventDescriptorCollection _events;
693                 PropertyDescriptorCollection _properties;
694                 
695                 public ComponentInfo (IComponent component): base (component.GetType())
696                 {
697                         _component = component;
698                 }
699                 
700                 public override AttributeCollection GetAttributes ()
701                 {
702                         return base.GetAttributes (_component);
703                 }
704                 
705                 public override EventDescriptorCollection GetEvents ()
706                 {
707                         if (_events != null) return _events;
708                         
709                         bool cache = true;
710                         EventInfo[] events = _component.GetType().GetEvents ();
711                         Hashtable t = new Hashtable ();
712                         foreach (EventInfo ev in events)
713                                 t [ev.Name] = new ReflectionEventDescriptor (ev);
714                                         
715                         if (_component.Site != null) 
716                         {
717                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
718                                 cache = filter.FilterEvents (_component, t);
719                         }
720                         
721                         ArrayList atts = new ArrayList ();
722                         atts.AddRange (t.Values);
723                         EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
724                         if (cache) _events = attCol;
725                         return attCol;
726                 }
727                 
728                 public override PropertyDescriptorCollection GetProperties ()
729                 {
730                         if (_properties != null) return _properties;
731                         
732                         bool cache = true;
733                         PropertyInfo[] props = _component.GetType().GetProperties ();
734                         Hashtable t = new Hashtable ();
735                         foreach (PropertyInfo pr in props)
736                                 t [pr.Name] = new ReflectionPropertyDescriptor (pr);
737                                         
738                         if (_component.Site != null) 
739                         {
740                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
741                                 cache = filter.FilterProperties (_component, t);
742                         }
743                         
744                         ArrayList atts = new ArrayList ();
745                         atts.AddRange (t.Values);
746                         PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (atts);
747                         if (cache) _properties = attCol;
748                         return attCol;
749                 }
750         }
751         
752         internal class TypeInfo : Info
753         {
754                 EventDescriptorCollection _events;
755                 PropertyDescriptorCollection _properties;
756                 
757                 public TypeInfo (Type t): base (t)
758                 {
759                 }
760                 
761                 public override AttributeCollection GetAttributes ()
762                 {
763                         return base.GetAttributes (null);
764                 }
765                 
766                 public override EventDescriptorCollection GetEvents ()
767                 {
768                         if (_events != null) return _events;
769                         
770                         EventInfo[] events = InfoType.GetEvents ();
771                         EventDescriptor[] descs = new EventDescriptor [events.Length];
772                         for (int n=0; n<events.Length; n++)
773                                 descs [n] = new ReflectionEventDescriptor (events[n]);
774
775                         _events = new EventDescriptorCollection (descs);
776                         return _events;
777                 }
778                 
779                 public override PropertyDescriptorCollection GetProperties ()
780                 {
781                         if (_properties != null) return _properties;
782                         
783                         PropertyInfo[] props = InfoType.GetProperties ();
784                         PropertyDescriptor[] descs = new PropertyDescriptor [props.Length];
785                         for (int n=0; n<props.Length; n++)
786                                 descs [n] = new ReflectionPropertyDescriptor (props[n]);
787
788                         _properties = new PropertyDescriptorCollection (descs);
789                         return _properties;
790                 }
791         }
792 }