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