2004-04-24 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 using System;
13 using System.Collections;
14 using System.Reflection;
15 using System.Globalization;
16 using System.ComponentModel.Design;
17
18 namespace System.ComponentModel
19 {
20
21 public sealed class TypeDescriptor
22 {
23         private static readonly string creatingDefaultConverters = "creatingDefaultConverters";
24         private static Hashtable defaultConverters;
25         private static IComNativeDescriptorHandler descriptorHandler;
26         private static Hashtable componentTable = new Hashtable ();
27         private static Hashtable typeTable = new Hashtable ();
28
29         private TypeDescriptor ()
30         {
31         }
32
33         [MonoTODO]
34         public static void AddEditorTable (Type editorBaseType, Hashtable table)
35         {
36                 throw new NotImplementedException ();
37         }
38
39         public static IDesigner CreateDesigner(IComponent component, Type designerBaseType)
40         {
41                 string tn = designerBaseType.AssemblyQualifiedName;
42                 AttributeCollection col = GetAttributes (component);
43                 
44                 foreach (Attribute at in col) {
45                         DesignerAttribute dat = at as DesignerAttribute;
46                         if (dat != null && tn == dat.DesignerBaseTypeName) {
47                                 return (IDesigner) Activator.CreateInstance (GetTypeFromName (component, dat.DesignerTypeName));
48                         }
49                 }
50                                 
51                 return null;
52         }
53
54         public static EventDescriptor CreateEvent (Type componentType,
55                                                    string name,
56                                                    Type type,
57                                                    Attribute [] attributes)
58         {
59                 return new ReflectionEventDescriptor (componentType, name, type, attributes);
60         }
61
62         public static EventDescriptor CreateEvent (Type componentType,
63                                                    EventDescriptor oldEventDescriptor,
64                                                    Attribute [] attributes)
65         {
66                 return new ReflectionEventDescriptor (componentType, oldEventDescriptor, attributes);
67         }
68
69         public static PropertyDescriptor CreateProperty (Type componentType,
70                                                          string name,
71                                                          Type type,
72                                                          Attribute [] attributes)
73         {
74                 return new ReflectionPropertyDescriptor (componentType, name, type, attributes);
75         }
76
77         public static PropertyDescriptor CreateProperty (Type componentType,
78                                                          PropertyDescriptor oldPropertyDescriptor,
79                                                          Attribute [] attributes)
80         {
81                 return new ReflectionPropertyDescriptor (componentType, oldPropertyDescriptor, attributes);
82         }
83
84         public static AttributeCollection GetAttributes (Type componentType)
85         {
86                 if (componentType == null)
87                         return AttributeCollection.Empty;
88
89                 return GetTypeInfo (componentType).GetAttributes ();
90         }
91
92         public static AttributeCollection GetAttributes (object component)
93         {
94                 return GetAttributes (component, false);
95         }
96
97         public static AttributeCollection GetAttributes (object component, bool noCustomTypeDesc)
98         {
99                 if (component == null)
100                     return AttributeCollection.Empty;
101
102                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
103                     return ((ICustomTypeDescriptor) component).GetAttributes ();
104                 } else {
105                         IComponent com = component as IComponent;
106                         if (com != null)
107                                 return GetComponentInfo (com).GetAttributes ();
108                         else
109                                 return GetTypeInfo (component.GetType()).GetAttributes ();
110                 }
111         }
112
113         public static string GetClassName (object component)
114         {
115                 return GetClassName (component, false);
116         }
117
118         public static string GetClassName (object component, bool noCustomTypeDesc)
119         {
120                 if (component == null)
121                     throw new ArgumentNullException ("component", "component cannot be null");
122
123                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
124                     return ((ICustomTypeDescriptor) component).GetClassName ();
125                 } else {
126                     return component.GetType ().FullName;
127                 }
128         }
129
130         public static string GetComponentName (object component)
131         {
132                 return GetComponentName (component, false);
133         }
134
135         public static string GetComponentName (object component, bool noCustomTypeDesc)
136         {
137                 if (component == null)
138                     throw new ArgumentNullException ("component", "component cannot be null");
139
140                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
141                     return ((ICustomTypeDescriptor) component).GetComponentName ();
142                 } else {
143                     if (((IComponent) component).Site == null)
144                                 return null;
145                     else
146                                 return ((IComponent) component).Site.Name;
147                 }
148         }
149
150         public static TypeConverter GetConverter (object component)
151         {
152                 return GetConverter (component.GetType ());
153         }
154
155         public static TypeConverter GetConverter (object component, bool noCustomTypeDesc)
156         {
157                 if (component == null)
158                         throw new ArgumentNullException ("component", "component cannot be null");
159
160                 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
161                         return ((ICustomTypeDescriptor) component).GetConverter ();
162                 } 
163                 else {
164                         Type t = null;
165                         AttributeCollection atts = GetAttributes (component, false);
166                         TypeConverterAttribute tca = (TypeConverterAttribute) atts[typeof(TypeConverterAttribute)];
167                         if (tca != null && tca.ConverterTypeName.Length > 0) {
168                                 t = GetTypeFromName (component as IComponent, tca.ConverterTypeName);
169                         }
170                         
171                         Type primitive = component.GetType ();
172                         while (t == null && primitive != typeof (object)) {
173                                 t = (Type) DefaultConverters [primitive];
174                                 if (t == null)
175                                         primitive = primitive.BaseType;
176                         }
177                         
178                         if (t != null)
179                                 return (TypeConverter) Activator.CreateInstance (t);
180                         else
181                                 return null;
182                 }
183         }
184
185         private static Hashtable DefaultConverters
186         {
187                 get {
188                         if (defaultConverters != null)
189                                 return defaultConverters;
190
191                         lock (creatingDefaultConverters) {
192                                 if (defaultConverters != null)
193                                         return defaultConverters;
194                                 
195                                 defaultConverters = new Hashtable ();
196                                 defaultConverters.Add (typeof (bool), typeof (BooleanConverter));
197                                 defaultConverters.Add (typeof (byte), typeof (ByteConverter));
198                                 defaultConverters.Add (typeof (sbyte), typeof (SByteConverter));
199                                 defaultConverters.Add (typeof (string), typeof (StringConverter));
200                                 defaultConverters.Add (typeof (char), typeof (CharConverter));
201                                 defaultConverters.Add (typeof (short), typeof (Int16Converter));
202                                 defaultConverters.Add (typeof (int), typeof (Int32Converter));
203                                 defaultConverters.Add (typeof (long), typeof (Int64Converter));
204                                 defaultConverters.Add (typeof (ushort), typeof (UInt16Converter));
205                                 defaultConverters.Add (typeof (uint), typeof (UInt32Converter));
206                                 defaultConverters.Add (typeof (ulong), typeof (UInt64Converter));
207                                 defaultConverters.Add (typeof (float), typeof (SingleConverter));
208                                 defaultConverters.Add (typeof (double), typeof (DoubleConverter));
209                                 defaultConverters.Add (typeof (decimal), typeof (DecimalConverter));
210                                 defaultConverters.Add (typeof (object), typeof (TypeConverter));
211                                 defaultConverters.Add (typeof (void), typeof (TypeConverter));
212                                 defaultConverters.Add (typeof (Array), typeof (ArrayConverter));
213                                 defaultConverters.Add (typeof (CultureInfo), typeof (CultureInfoConverter));
214                                 defaultConverters.Add (typeof (DateTime), typeof (DateTimeConverter));
215                                 defaultConverters.Add (typeof (Guid), typeof (GuidConverter));
216                                 defaultConverters.Add (typeof (TimeSpan), typeof (TimeSpanConverter));
217                                 defaultConverters.Add (typeof (ICollection), typeof (CollectionConverter));
218                                 //FIXME We need to add the type for the ReferenceConverter
219                                 //defaultConverters.Add (typeof (????), typeof (ReferenceConverter));
220                         }
221                         return defaultConverters;
222                 }
223         }
224         
225         public static TypeConverter GetConverter (Type type)
226         {
227                 if (type.IsEnum) {
228                         // EnumConverter needs to know the enum type
229                         return new EnumConverter(type);
230                 } else {
231                         TypeConverterAttribute tca = null;
232                         Type t = null;
233                         object [] atts = type.GetCustomAttributes (typeof(TypeConverterAttribute), true);
234                         
235                         if (atts.Length > 0)
236                                 tca = (TypeConverterAttribute)atts[0];
237                         
238                         if (tca != null) {
239                                 t = GetTypeFromName (null, tca.ConverterTypeName);
240                         }
241                         
242                         Type primitive = type;
243                         while (t == null && primitive != typeof (object)) {
244                                 t = (Type) DefaultConverters [primitive];
245                                 if (t == null)
246                                         primitive = primitive.BaseType;
247                         }
248                         
249                         if (t != null)
250                                 return (TypeConverter) Activator.CreateInstance (t);
251                         else
252                                 return null;
253                 }
254         }
255
256         public static EventDescriptor GetDefaultEvent (Type componentType)
257         {
258                 return GetTypeInfo (componentType).GetDefaultEvent ();
259         }
260
261         public static EventDescriptor GetDefaultEvent (object component)
262         {
263                 return GetDefaultEvent (component, false);
264         }
265
266         public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
267         {
268                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
269                         return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
270                 else {
271                         IComponent com = component as IComponent;
272                         if (com != null)
273                                 return GetComponentInfo (com).GetDefaultEvent ();
274                         else
275                                 return GetTypeInfo (component.GetType()).GetDefaultEvent ();
276                 }
277         }
278
279         public static PropertyDescriptor GetDefaultProperty (Type componentType)
280         {
281                 return GetTypeInfo (componentType).GetDefaultProperty ();
282         }
283
284         public static PropertyDescriptor GetDefaultProperty (object component)
285         {
286                 return GetDefaultProperty (component, false);
287         }
288
289         public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
290         {
291                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
292                         return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
293                 else {
294                         IComponent com = component as IComponent;
295                         if (com != null)
296                                 return GetComponentInfo (com).GetDefaultProperty ();
297                         else
298                                 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
299                 }
300         }
301
302         [MonoTODO]
303         public static object GetEditor (Type componentType, Type editorBaseType)
304         {
305                 throw new NotImplementedException ();
306         }
307
308         public static object GetEditor (object component, Type editorBaseType)
309         {
310                 return GetEditor (component, editorBaseType, false);
311         }
312
313         [MonoTODO]
314         public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
315         {
316                 throw new NotImplementedException ();
317         }
318
319         public static EventDescriptorCollection GetEvents (object component)
320         {
321                 return GetEvents (component, false);
322         }
323
324         public static EventDescriptorCollection GetEvents (Type componentType)
325         {
326                 return GetEvents (componentType, null);
327         }
328
329         public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes)
330         {
331                 return GetEvents (component, attributes, false);
332         }
333
334         public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
335         {
336                 return GetEvents (component, null, noCustomTypeDesc);
337         }
338
339         public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
340         {
341                 return GetTypeInfo (componentType).GetEvents (attributes);
342         }
343
344         public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
345         {
346                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
347                         return ((ICustomTypeDescriptor) component).GetEvents (attributes);
348                 else {
349                         IComponent com = component as IComponent;
350                         if (com != null)
351                                 return GetComponentInfo (com).GetEvents (attributes);
352                         else
353                                 return GetTypeInfo (component.GetType()).GetEvents (attributes);
354                 }
355         }
356
357         public static PropertyDescriptorCollection GetProperties (object component)
358         {
359                 return GetProperties (component, false);
360         }
361
362         public static PropertyDescriptorCollection GetProperties (Type componentType)
363         {
364                 return GetProperties (componentType, null);
365         }
366
367         public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes)
368         {
369                 return GetProperties (component, attributes, false);
370         }
371
372         public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
373         {
374                 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
375                         return ((ICustomTypeDescriptor) component).GetProperties (attributes);
376                 else {
377                         IComponent com = component as IComponent;
378                         if (com != null)
379                                 return GetComponentInfo (com).GetProperties (attributes);
380                         else
381                                 return GetTypeInfo (component.GetType()).GetProperties (attributes);
382                 }
383         }
384
385         public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
386         {
387                 return GetProperties (component, null, noCustomTypeDesc);
388         }
389
390         public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
391         {
392                 return GetTypeInfo (componentType).GetProperties (attributes);
393         }
394
395         public static void SortDescriptorArray (IList infos)
396         {
397                 string[] names = new string [infos.Count];
398                 object[] values = new object [infos.Count];
399                 for (int n=0; n<names.Length; n++) {
400                         names[n] = ((MemberDescriptor)infos[n]).Name;
401                         values[n] = infos[n];
402                 }
403                 Array.Sort (names, values);
404                 infos.Clear();
405                 foreach (object ob in values)
406                         infos.Add (ob);
407         }
408
409         public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
410                 get { return descriptorHandler; }
411                 set { descriptorHandler = value; }
412         }
413
414         public static void Refresh (Assembly assembly)
415         {
416                 foreach (Type type in assembly.GetTypes())
417                         Refresh (type);
418         }
419
420         public static void Refresh (Module module)
421         {
422                 foreach (Type type in module.GetTypes())
423                         Refresh (type);
424         }
425
426         public static void Refresh (object component)
427         {
428                 lock (componentTable)
429                 {
430                         componentTable.Remove (component);
431                 }
432                 if (Refreshed != null) Refreshed (new RefreshEventArgs (component));
433         }
434
435         public static void Refresh (Type type)
436         {
437                 lock (typeTable)
438                 {
439                         typeTable.Remove (type);
440                 }
441                 if (Refreshed != null) Refreshed (new RefreshEventArgs (type));
442         }
443
444         public static event RefreshEventHandler Refreshed;
445         
446         internal static ComponentInfo GetComponentInfo (IComponent com)
447         {
448                 lock (componentTable)
449                 {
450                         ComponentInfo ci = (ComponentInfo) componentTable [com];
451                         if (ci == null) {
452                                 ci = new ComponentInfo (com);
453                                 componentTable [com] = ci;
454                         }
455                         return ci;
456                 }
457         }
458         
459         internal static TypeInfo GetTypeInfo (Type type)
460         {
461                 lock (typeTable)
462                 {
463                         TypeInfo ci = (TypeInfo) typeTable [type];
464                         if (ci == null) {
465                                 ci = new TypeInfo (type);
466                                 typeTable [type] = ci;
467                         }
468                         return ci;
469                 }
470         }
471         
472         static Type GetTypeFromName (IComponent component, string typeName)
473         {
474                 if (component != null && component.Site != null) {
475                         ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
476                         if (resver != null) return resver.GetType (typeName, true, false);
477                 }
478                 
479                 Type t = Type.GetType (typeName);
480                 if (t == null) throw new ArgumentException ("Type '" + typeName + "' not found");
481                 return t;
482         }
483 }
484
485         internal abstract class Info
486         {
487                 Type _infoType;
488                 EventDescriptor _defaultEvent;
489                 bool _gotDefaultEvent;
490                 PropertyDescriptor _defaultProperty;
491                 bool _gotDefaultProperty;
492                 
493                 public Info (Type infoType)
494                 {
495                         _infoType = infoType;
496                 }
497                 
498                 public abstract AttributeCollection GetAttributes ();
499                 public abstract EventDescriptorCollection GetEvents ();
500                 public abstract PropertyDescriptorCollection GetProperties ();
501                 
502                 public Type InfoType
503                 {
504                         get { return _infoType; }
505                 }
506                 
507                 public EventDescriptorCollection GetEvents (Attribute[] attributes)
508                 {
509                         EventDescriptorCollection evs = GetEvents ();
510                         if (attributes == null) return evs;
511                         else return evs.Filter (attributes);
512                 }
513                 
514                 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
515                 {
516                         PropertyDescriptorCollection props = GetProperties ();
517                         if (attributes == null) return props;
518                         else return props.Filter (attributes);
519                 }
520                 
521                 public EventDescriptor GetDefaultEvent ()
522                 {
523                         if (_gotDefaultEvent) return _defaultEvent;
524                         
525                         DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
526                         if (attr == null || attr.Name == null) 
527                                 _defaultEvent = null;
528                         else {
529                                 EventInfo ei = _infoType.GetEvent (attr.Name);
530                                 if (ei == null)
531                                         throw new ArgumentException ("Event '" + attr.Name + "' not found in class " + _infoType);
532                                 _defaultEvent = new ReflectionEventDescriptor (ei);
533                         }
534                         _gotDefaultEvent = true;
535                         return _defaultEvent;
536                 }
537                 
538                 public PropertyDescriptor GetDefaultProperty ()
539                 {
540                         if (_gotDefaultProperty) return _defaultProperty;
541                         
542                         DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
543                         if (attr == null || attr.Name == null) 
544                                 _defaultProperty = null;
545                         else {
546                                 PropertyInfo ei = _infoType.GetProperty (attr.Name);
547                                 if (ei == null)
548                                         throw new ArgumentException ("Property '" + attr.Name + "' not found in class " + _infoType);
549                                 _defaultProperty = new ReflectionPropertyDescriptor (ei);
550                         }
551                         _gotDefaultProperty = true;
552                         return _defaultProperty;
553                 }
554         }
555
556         internal class ComponentInfo : Info
557         {
558                 IComponent _component;
559                 AttributeCollection _attributes;
560                 EventDescriptorCollection _events;
561                 PropertyDescriptorCollection _properties;
562                 
563                 public ComponentInfo (IComponent component): base (component.GetType())
564                 {
565                         _component = component;
566                 }
567                 
568                 public override AttributeCollection GetAttributes ()
569                 {
570                         if (_attributes != null) return _attributes;
571                         
572                         bool cache = true;
573                         object[] ats = _component.GetType().GetCustomAttributes (true);
574                         Hashtable t = new Hashtable ();
575                         foreach (Attribute at in ats)
576                                 t [at.TypeId] = at;
577                                         
578                         if (_component.Site != null) 
579                         {
580                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
581                                 cache = filter.FilterAttributes (_component, t);
582                         }
583                         
584                         ArrayList atts = new ArrayList ();
585                         atts.AddRange (t.Values);
586                         AttributeCollection attCol = new AttributeCollection (atts);
587                         if (cache) _attributes = attCol;
588                         return attCol;
589                 }
590                 
591                 public override EventDescriptorCollection GetEvents ()
592                 {
593                         if (_events != null) return _events;
594                         
595                         bool cache = true;
596                         EventInfo[] events = _component.GetType().GetEvents ();
597                         Hashtable t = new Hashtable ();
598                         foreach (EventInfo ev in events)
599                                 t [ev.Name] = new ReflectionEventDescriptor (ev);
600                                         
601                         if (_component.Site != null) 
602                         {
603                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
604                                 cache = filter.FilterEvents (_component, t);
605                         }
606                         
607                         ArrayList atts = new ArrayList ();
608                         atts.AddRange (t.Values);
609                         EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
610                         if (cache) _events = attCol;
611                         return attCol;
612                 }
613                 
614                 public override PropertyDescriptorCollection GetProperties ()
615                 {
616                         if (_properties != null) return _properties;
617                         
618                         bool cache = true;
619                         PropertyInfo[] props = _component.GetType().GetProperties ();
620                         Hashtable t = new Hashtable ();
621                         foreach (PropertyInfo pr in props)
622                                 t [pr.Name] = new ReflectionPropertyDescriptor (pr);
623                                         
624                         if (_component.Site != null) 
625                         {
626                                 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
627                                 cache = filter.FilterProperties (_component, t);
628                         }
629                         
630                         ArrayList atts = new ArrayList ();
631                         atts.AddRange (t.Values);
632                         PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (atts);
633                         if (cache) _properties = attCol;
634                         return attCol;
635                 }
636         }
637         
638         internal class TypeInfo : Info
639         {
640                 AttributeCollection _attributes;
641                 EventDescriptorCollection _events;
642                 PropertyDescriptorCollection _properties;
643                 
644                 public TypeInfo (Type t): base (t)
645                 {
646                 }
647                 
648                 public override AttributeCollection GetAttributes ()
649                 {
650                         if (_attributes != null) return _attributes;
651                         
652                         object[] atts = InfoType.GetCustomAttributes (true);
653                         _attributes = new AttributeCollection ((Attribute[]) atts);
654                         return _attributes;
655                 }
656                 
657                 public override EventDescriptorCollection GetEvents ()
658                 {
659                         if (_events != null) return _events;
660                         
661                         EventInfo[] events = InfoType.GetEvents ();
662                         EventDescriptor[] descs = new EventDescriptor [events.Length];
663                         for (int n=0; n<events.Length; n++)
664                                 descs [n] = new ReflectionEventDescriptor (events[n]);
665
666                         _events = new EventDescriptorCollection (descs);
667                         return _events;
668                 }
669                 
670                 public override PropertyDescriptorCollection GetProperties ()
671                 {
672                         if (_properties != null) return _properties;
673                         
674                         PropertyInfo[] props = InfoType.GetProperties ();
675                         PropertyDescriptor[] descs = new PropertyDescriptor [props.Length];
676                         for (int n=0; n<props.Length; n++)
677                                 descs [n] = new ReflectionPropertyDescriptor (props[n]);
678
679                         _properties = new PropertyDescriptorCollection (descs);
680                         return _properties;
681                 }
682         }
683 }
684