**** Merged from MCS ****
[mono-project.git] / mcs / class / System / System.ComponentModel / TypeDescriptor.cs
blob011b42f5052cc7f7f4def7d78d4f507cbfcc0a99
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
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.
33 using System;
34 using System.Collections;
35 using System.Reflection;
36 using System.Globalization;
37 using System.ComponentModel.Design;
39 namespace System.ComponentModel
42 public sealed class TypeDescriptor
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 ();
50 private TypeDescriptor ()
54 [MonoTODO]
55 public static void AddEditorTable (Type editorBaseType, Hashtable table)
57 throw new NotImplementedException ();
60 public static IDesigner CreateDesigner(IComponent component, Type designerBaseType)
62 string tn = designerBaseType.AssemblyQualifiedName;
63 AttributeCollection col = GetAttributes (component);
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));
72 return null;
75 public static EventDescriptor CreateEvent (Type componentType,
76 string name,
77 Type type,
78 Attribute [] attributes)
80 return new ReflectionEventDescriptor (componentType, name, type, attributes);
83 public static EventDescriptor CreateEvent (Type componentType,
84 EventDescriptor oldEventDescriptor,
85 Attribute [] attributes)
87 return new ReflectionEventDescriptor (componentType, oldEventDescriptor, attributes);
90 public static PropertyDescriptor CreateProperty (Type componentType,
91 string name,
92 Type type,
93 Attribute [] attributes)
95 return new ReflectionPropertyDescriptor (componentType, name, type, attributes);
98 public static PropertyDescriptor CreateProperty (Type componentType,
99 PropertyDescriptor oldPropertyDescriptor,
100 Attribute [] attributes)
102 return new ReflectionPropertyDescriptor (componentType, oldPropertyDescriptor, attributes);
105 public static AttributeCollection GetAttributes (Type componentType)
107 if (componentType == null)
108 return AttributeCollection.Empty;
110 return GetTypeInfo (componentType).GetAttributes ();
113 public static AttributeCollection GetAttributes (object component)
115 return GetAttributes (component, false);
118 public static AttributeCollection GetAttributes (object component, bool noCustomTypeDesc)
120 if (component == null)
121 return AttributeCollection.Empty;
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 ();
134 public static string GetClassName (object component)
136 return GetClassName (component, false);
139 public static string GetClassName (object component, bool noCustomTypeDesc)
141 if (component == null)
142 throw new ArgumentNullException ("component", "component cannot be null");
144 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
145 return ((ICustomTypeDescriptor) component).GetClassName ();
146 } else {
147 return component.GetType ().FullName;
151 public static string GetComponentName (object component)
153 return GetComponentName (component, false);
156 public static string GetComponentName (object component, bool noCustomTypeDesc)
158 if (component == null)
159 throw new ArgumentNullException ("component", "component cannot be null");
161 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
162 return ((ICustomTypeDescriptor) component).GetComponentName ();
163 } else {
164 if (((IComponent) component).Site == null)
165 return null;
166 else
167 return ((IComponent) component).Site.Name;
171 public static TypeConverter GetConverter (object component)
173 return GetConverter (component.GetType ());
176 public static TypeConverter GetConverter (object component, bool noCustomTypeDesc)
178 if (component == null)
179 throw new ArgumentNullException ("component", "component cannot be null");
181 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
182 return ((ICustomTypeDescriptor) component).GetConverter ();
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);
192 Type primitive = component.GetType ();
193 while (t == null && primitive != typeof (object)) {
194 t = (Type) DefaultConverters [primitive];
195 if (t == null)
196 primitive = primitive.BaseType;
199 if (t != null)
200 return (TypeConverter) Activator.CreateInstance (t);
201 else
202 return null;
206 private static Hashtable DefaultConverters
208 get {
209 if (defaultConverters != null)
210 return defaultConverters;
212 lock (creatingDefaultConverters) {
213 if (defaultConverters != null)
214 return defaultConverters;
216 defaultConverters = new Hashtable ();
217 defaultConverters.Add (typeof (bool), typeof (BooleanConverter));
218 defaultConverters.Add (typeof (byte), typeof (ByteConverter));
219 defaultConverters.Add (typeof (sbyte), typeof (SByteConverter));
220 defaultConverters.Add (typeof (string), typeof (StringConverter));
221 defaultConverters.Add (typeof (char), typeof (CharConverter));
222 defaultConverters.Add (typeof (short), typeof (Int16Converter));
223 defaultConverters.Add (typeof (int), typeof (Int32Converter));
224 defaultConverters.Add (typeof (long), typeof (Int64Converter));
225 defaultConverters.Add (typeof (ushort), typeof (UInt16Converter));
226 defaultConverters.Add (typeof (uint), typeof (UInt32Converter));
227 defaultConverters.Add (typeof (ulong), typeof (UInt64Converter));
228 defaultConverters.Add (typeof (float), typeof (SingleConverter));
229 defaultConverters.Add (typeof (double), typeof (DoubleConverter));
230 defaultConverters.Add (typeof (decimal), typeof (DecimalConverter));
231 defaultConverters.Add (typeof (object), typeof (TypeConverter));
232 defaultConverters.Add (typeof (void), typeof (TypeConverter));
233 defaultConverters.Add (typeof (Array), typeof (ArrayConverter));
234 defaultConverters.Add (typeof (CultureInfo), typeof (CultureInfoConverter));
235 defaultConverters.Add (typeof (DateTime), typeof (DateTimeConverter));
236 defaultConverters.Add (typeof (Guid), typeof (GuidConverter));
237 defaultConverters.Add (typeof (TimeSpan), typeof (TimeSpanConverter));
238 defaultConverters.Add (typeof (ICollection), typeof (CollectionConverter));
239 //FIXME We need to add the type for the ReferenceConverter
240 //defaultConverters.Add (typeof (????), typeof (ReferenceConverter));
242 return defaultConverters;
246 public static TypeConverter GetConverter (Type type)
248 if (type.IsEnum) {
249 // EnumConverter needs to know the enum type
250 return new EnumConverter(type);
251 } else {
252 TypeConverterAttribute tca = null;
253 Type t = null;
254 object [] atts = type.GetCustomAttributes (typeof(TypeConverterAttribute), true);
256 if (atts.Length > 0)
257 tca = (TypeConverterAttribute)atts[0];
259 if (tca != null) {
260 t = GetTypeFromName (null, tca.ConverterTypeName);
263 Type primitive = type;
264 while (t == null && primitive != typeof (object)) {
265 t = (Type) DefaultConverters [primitive];
266 if (t == null)
267 primitive = primitive.BaseType;
270 if (t != null)
271 return (TypeConverter) Activator.CreateInstance (t);
272 else
273 return null;
277 public static EventDescriptor GetDefaultEvent (Type componentType)
279 return GetTypeInfo (componentType).GetDefaultEvent ();
282 public static EventDescriptor GetDefaultEvent (object component)
284 return GetDefaultEvent (component, false);
287 public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
289 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
290 return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
291 else {
292 IComponent com = component as IComponent;
293 if (com != null)
294 return GetComponentInfo (com).GetDefaultEvent ();
295 else
296 return GetTypeInfo (component.GetType()).GetDefaultEvent ();
300 public static PropertyDescriptor GetDefaultProperty (Type componentType)
302 return GetTypeInfo (componentType).GetDefaultProperty ();
305 public static PropertyDescriptor GetDefaultProperty (object component)
307 return GetDefaultProperty (component, false);
310 public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
312 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
313 return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
314 else {
315 IComponent com = component as IComponent;
316 if (com != null)
317 return GetComponentInfo (com).GetDefaultProperty ();
318 else
319 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
323 [MonoTODO]
324 public static object GetEditor (Type componentType, Type editorBaseType)
326 throw new NotImplementedException ();
329 public static object GetEditor (object component, Type editorBaseType)
331 return GetEditor (component, editorBaseType, false);
334 [MonoTODO]
335 public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
337 throw new NotImplementedException ();
340 public static EventDescriptorCollection GetEvents (object component)
342 return GetEvents (component, false);
345 public static EventDescriptorCollection GetEvents (Type componentType)
347 return GetEvents (componentType, null);
350 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes)
352 return GetEvents (component, attributes, false);
355 public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
357 return GetEvents (component, null, noCustomTypeDesc);
360 public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
362 return GetTypeInfo (componentType).GetEvents (attributes);
365 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
367 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
368 return ((ICustomTypeDescriptor) component).GetEvents (attributes);
369 else {
370 IComponent com = component as IComponent;
371 if (com != null)
372 return GetComponentInfo (com).GetEvents (attributes);
373 else
374 return GetTypeInfo (component.GetType()).GetEvents (attributes);
378 public static PropertyDescriptorCollection GetProperties (object component)
380 return GetProperties (component, false);
383 public static PropertyDescriptorCollection GetProperties (Type componentType)
385 return GetProperties (componentType, null);
388 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes)
390 return GetProperties (component, attributes, false);
393 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
395 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
396 return ((ICustomTypeDescriptor) component).GetProperties (attributes);
397 else {
398 IComponent com = component as IComponent;
399 if (com != null)
400 return GetComponentInfo (com).GetProperties (attributes);
401 else
402 return GetTypeInfo (component.GetType()).GetProperties (attributes);
406 public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
408 return GetProperties (component, null, noCustomTypeDesc);
411 public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
413 return GetTypeInfo (componentType).GetProperties (attributes);
416 public static void SortDescriptorArray (IList infos)
418 string[] names = new string [infos.Count];
419 object[] values = new object [infos.Count];
420 for (int n=0; n<names.Length; n++) {
421 names[n] = ((MemberDescriptor)infos[n]).Name;
422 values[n] = infos[n];
424 Array.Sort (names, values);
425 infos.Clear();
426 foreach (object ob in values)
427 infos.Add (ob);
430 public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
431 get { return descriptorHandler; }
432 set { descriptorHandler = value; }
435 public static void Refresh (Assembly assembly)
437 foreach (Type type in assembly.GetTypes())
438 Refresh (type);
441 public static void Refresh (Module module)
443 foreach (Type type in module.GetTypes())
444 Refresh (type);
447 public static void Refresh (object component)
449 lock (componentTable)
451 componentTable.Remove (component);
453 if (Refreshed != null) Refreshed (new RefreshEventArgs (component));
456 public static void Refresh (Type type)
458 lock (typeTable)
460 typeTable.Remove (type);
462 if (Refreshed != null) Refreshed (new RefreshEventArgs (type));
465 static EventHandler onDispose;
467 static void OnComponentDisposed (object sender, EventArgs args)
469 lock (componentTable) {
470 componentTable.Remove (sender);
474 public static event RefreshEventHandler Refreshed;
476 internal static ComponentInfo GetComponentInfo (IComponent com)
478 lock (componentTable)
480 ComponentInfo ci = (ComponentInfo) componentTable [com];
481 if (ci == null) {
482 if (onDispose == null)
483 onDispose = new EventHandler (OnComponentDisposed);
485 com.Disposed += onDispose;
486 ci = new ComponentInfo (com);
487 componentTable [com] = ci;
489 return ci;
493 internal static TypeInfo GetTypeInfo (Type type)
495 lock (typeTable)
497 TypeInfo ci = (TypeInfo) typeTable [type];
498 if (ci == null) {
499 ci = new TypeInfo (type);
500 typeTable [type] = ci;
502 return ci;
506 static Type GetTypeFromName (IComponent component, string typeName)
508 if (component != null && component.Site != null) {
509 ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
510 if (resver != null) return resver.GetType (typeName, true, false);
513 Type t = Type.GetType (typeName);
514 if (t == null) throw new ArgumentException ("Type '" + typeName + "' not found");
515 return t;
519 internal abstract class Info
521 Type _infoType;
522 EventDescriptor _defaultEvent;
523 bool _gotDefaultEvent;
524 PropertyDescriptor _defaultProperty;
525 bool _gotDefaultProperty;
526 AttributeCollection _attributes;
528 public Info (Type infoType)
530 _infoType = infoType;
533 public abstract AttributeCollection GetAttributes ();
534 public abstract EventDescriptorCollection GetEvents ();
535 public abstract PropertyDescriptorCollection GetProperties ();
537 public Type InfoType
539 get { return _infoType; }
542 public EventDescriptorCollection GetEvents (Attribute[] attributes)
544 EventDescriptorCollection evs = GetEvents ();
545 if (attributes == null) return evs;
546 else return evs.Filter (attributes);
549 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
551 PropertyDescriptorCollection props = GetProperties ();
552 if (attributes == null) return props;
553 else return props.Filter (attributes);
556 public EventDescriptor GetDefaultEvent ()
558 if (_gotDefaultEvent) return _defaultEvent;
560 DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
561 if (attr == null || attr.Name == null)
562 _defaultEvent = null;
563 else {
564 EventInfo ei = _infoType.GetEvent (attr.Name);
565 if (ei == null)
566 throw new ArgumentException ("Event '" + attr.Name + "' not found in class " + _infoType);
567 _defaultEvent = new ReflectionEventDescriptor (ei);
569 _gotDefaultEvent = true;
570 return _defaultEvent;
573 public PropertyDescriptor GetDefaultProperty ()
575 if (_gotDefaultProperty) return _defaultProperty;
577 DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
578 if (attr == null || attr.Name == null)
579 _defaultProperty = null;
580 else {
581 PropertyInfo ei = _infoType.GetProperty (attr.Name);
582 if (ei == null)
583 throw new ArgumentException ("Property '" + attr.Name + "' not found in class " + _infoType);
584 _defaultProperty = new ReflectionPropertyDescriptor (ei);
586 _gotDefaultProperty = true;
587 return _defaultProperty;
590 protected AttributeCollection GetAttributes (IComponent comp)
592 if (_attributes != null) return _attributes;
594 bool cache = true;
595 object[] ats = _infoType.GetCustomAttributes (true);
596 Hashtable t = new Hashtable ();
597 foreach (Attribute at in ats)
598 t [at.TypeId] = at;
600 if (comp != null && comp.Site != null)
602 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) comp.Site.GetService (typeof(ITypeDescriptorFilterService));
603 cache = filter.FilterAttributes (comp, t);
606 ArrayList atts = new ArrayList ();
607 atts.AddRange (t.Values);
608 AttributeCollection attCol = new AttributeCollection (atts);
609 if (cache) _attributes = attCol;
610 return attCol;
614 internal class ComponentInfo : Info
616 IComponent _component;
617 EventDescriptorCollection _events;
618 PropertyDescriptorCollection _properties;
620 public ComponentInfo (IComponent component): base (component.GetType())
622 _component = component;
625 public override AttributeCollection GetAttributes ()
627 return base.GetAttributes (_component);
630 public override EventDescriptorCollection GetEvents ()
632 if (_events != null) return _events;
634 bool cache = true;
635 EventInfo[] events = _component.GetType().GetEvents ();
636 Hashtable t = new Hashtable ();
637 foreach (EventInfo ev in events)
638 t [ev.Name] = new ReflectionEventDescriptor (ev);
640 if (_component.Site != null)
642 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
643 cache = filter.FilterEvents (_component, t);
646 ArrayList atts = new ArrayList ();
647 atts.AddRange (t.Values);
648 EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
649 if (cache) _events = attCol;
650 return attCol;
653 public override PropertyDescriptorCollection GetProperties ()
655 if (_properties != null) return _properties;
657 bool cache = true;
658 PropertyInfo[] props = _component.GetType().GetProperties ();
659 Hashtable t = new Hashtable ();
660 foreach (PropertyInfo pr in props)
661 t [pr.Name] = new ReflectionPropertyDescriptor (pr);
663 if (_component.Site != null)
665 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
666 cache = filter.FilterProperties (_component, t);
669 ArrayList atts = new ArrayList ();
670 atts.AddRange (t.Values);
671 PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (atts);
672 if (cache) _properties = attCol;
673 return attCol;
677 internal class TypeInfo : Info
679 EventDescriptorCollection _events;
680 PropertyDescriptorCollection _properties;
682 public TypeInfo (Type t): base (t)
686 public override AttributeCollection GetAttributes ()
688 return base.GetAttributes (null);
691 public override EventDescriptorCollection GetEvents ()
693 if (_events != null) return _events;
695 EventInfo[] events = InfoType.GetEvents ();
696 EventDescriptor[] descs = new EventDescriptor [events.Length];
697 for (int n=0; n<events.Length; n++)
698 descs [n] = new ReflectionEventDescriptor (events[n]);
700 _events = new EventDescriptorCollection (descs);
701 return _events;
704 public override PropertyDescriptorCollection GetProperties ()
706 if (_properties != null) return _properties;
708 PropertyInfo[] props = InfoType.GetProperties ();
709 PropertyDescriptor[] descs = new PropertyDescriptor [props.Length];
710 for (int n=0; n<props.Length; n++)
711 descs [n] = new ReflectionPropertyDescriptor (props[n]);
713 _properties = new PropertyDescriptorCollection (descs);
714 return _properties;