2 // System.ComponentModel.TypeDescriptor.cs
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 // (C) 2002 Ximian, Inc (http://www.ximian.com)
9 // (C) 2003 Andreas Nahr
13 using System.Collections;
14 using System.Reflection;
15 using System.Globalization;
16 using System.ComponentModel.Design;
18 namespace System.ComponentModel
21 public sealed class TypeDescriptor
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 ();
29 private TypeDescriptor ()
34 public static void AddEditorTable (Type editorBaseType, Hashtable table)
36 throw new NotImplementedException ();
39 public static IDesigner CreateDesigner(IComponent component, Type designerBaseType)
41 string tn = designerBaseType.AssemblyQualifiedName;
42 AttributeCollection col = GetAttributes (component);
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));
54 public static EventDescriptor CreateEvent (Type componentType,
57 Attribute [] attributes)
59 return new ReflectionEventDescriptor (componentType, name, type, attributes);
62 public static EventDescriptor CreateEvent (Type componentType,
63 EventDescriptor oldEventDescriptor,
64 Attribute [] attributes)
66 return new ReflectionEventDescriptor (componentType, oldEventDescriptor, attributes);
69 public static PropertyDescriptor CreateProperty (Type componentType,
72 Attribute [] attributes)
74 return new ReflectionPropertyDescriptor (componentType, name, type, attributes);
77 public static PropertyDescriptor CreateProperty (Type componentType,
78 PropertyDescriptor oldPropertyDescriptor,
79 Attribute [] attributes)
81 return new ReflectionPropertyDescriptor (componentType, oldPropertyDescriptor, attributes);
84 public static AttributeCollection GetAttributes (Type componentType)
86 if (componentType == null)
87 return AttributeCollection.Empty;
89 return GetTypeInfo (componentType).GetAttributes ();
92 public static AttributeCollection GetAttributes (object component)
94 return GetAttributes (component, false);
97 public static AttributeCollection GetAttributes (object component, bool noCustomTypeDesc)
99 if (component == null)
100 return AttributeCollection.Empty;
102 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
103 return ((ICustomTypeDescriptor) component).GetAttributes ();
105 IComponent com = component as IComponent;
107 return GetComponentInfo (com).GetAttributes ();
109 return GetTypeInfo (component.GetType()).GetAttributes ();
113 public static string GetClassName (object component)
115 return GetClassName (component, false);
118 public static string GetClassName (object component, bool noCustomTypeDesc)
120 if (component == null)
121 throw new ArgumentNullException ("component", "component cannot be null");
123 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
124 return ((ICustomTypeDescriptor) component).GetClassName ();
126 return component.GetType ().FullName;
130 public static string GetComponentName (object component)
132 return GetComponentName (component, false);
135 public static string GetComponentName (object component, bool noCustomTypeDesc)
137 if (component == null)
138 throw new ArgumentNullException ("component", "component cannot be null");
140 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
141 return ((ICustomTypeDescriptor) component).GetComponentName ();
143 if (((IComponent) component).Site == null)
146 return ((IComponent) component).Site.Name;
150 public static TypeConverter GetConverter (object component)
152 return GetConverter (component.GetType ());
155 public static TypeConverter GetConverter (object component, bool noCustomTypeDesc)
157 if (component == null)
158 throw new ArgumentNullException ("component", "component cannot be null");
160 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
161 return ((ICustomTypeDescriptor) component).GetConverter ();
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);
171 Type primitive = component.GetType ();
172 while (t == null && primitive != typeof (object)) {
173 t = (Type) DefaultConverters [primitive];
175 primitive = primitive.BaseType;
179 return (TypeConverter) Activator.CreateInstance (t);
185 private static Hashtable DefaultConverters
188 if (defaultConverters != null)
189 return defaultConverters;
191 lock (creatingDefaultConverters) {
192 if (defaultConverters != null)
193 return defaultConverters;
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));
221 return defaultConverters;
225 public static TypeConverter GetConverter (Type type)
228 // EnumConverter needs to know the enum type
229 return new EnumConverter(type);
231 TypeConverterAttribute tca = null;
233 object [] atts = type.GetCustomAttributes (typeof(TypeConverterAttribute), true);
236 tca = (TypeConverterAttribute)atts[0];
239 t = GetTypeFromName (null, tca.ConverterTypeName);
242 Type primitive = type;
243 while (t == null && primitive != typeof (object)) {
244 t = (Type) DefaultConverters [primitive];
246 primitive = primitive.BaseType;
250 return (TypeConverter) Activator.CreateInstance (t);
256 public static EventDescriptor GetDefaultEvent (Type componentType)
258 return GetTypeInfo (componentType).GetDefaultEvent ();
261 public static EventDescriptor GetDefaultEvent (object component)
263 return GetDefaultEvent (component, false);
266 public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
268 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
269 return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
271 IComponent com = component as IComponent;
273 return GetComponentInfo (com).GetDefaultEvent ();
275 return GetTypeInfo (component.GetType()).GetDefaultEvent ();
279 public static PropertyDescriptor GetDefaultProperty (Type componentType)
281 return GetTypeInfo (componentType).GetDefaultProperty ();
284 public static PropertyDescriptor GetDefaultProperty (object component)
286 return GetDefaultProperty (component, false);
289 public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
291 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
292 return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
294 IComponent com = component as IComponent;
296 return GetComponentInfo (com).GetDefaultProperty ();
298 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
303 public static object GetEditor (Type componentType, Type editorBaseType)
305 throw new NotImplementedException ();
308 public static object GetEditor (object component, Type editorBaseType)
310 return GetEditor (component, editorBaseType, false);
314 public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
316 throw new NotImplementedException ();
319 public static EventDescriptorCollection GetEvents (object component)
321 return GetEvents (component, false);
324 public static EventDescriptorCollection GetEvents (Type componentType)
326 return GetEvents (componentType, null);
329 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes)
331 return GetEvents (component, attributes, false);
334 public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
336 return GetEvents (component, null, noCustomTypeDesc);
339 public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
341 return GetTypeInfo (componentType).GetEvents (attributes);
344 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
346 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
347 return ((ICustomTypeDescriptor) component).GetEvents (attributes);
349 IComponent com = component as IComponent;
351 return GetComponentInfo (com).GetEvents (attributes);
353 return GetTypeInfo (component.GetType()).GetEvents (attributes);
357 public static PropertyDescriptorCollection GetProperties (object component)
359 return GetProperties (component, false);
362 public static PropertyDescriptorCollection GetProperties (Type componentType)
364 return GetProperties (componentType, null);
367 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes)
369 return GetProperties (component, attributes, false);
372 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
374 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
375 return ((ICustomTypeDescriptor) component).GetProperties (attributes);
377 IComponent com = component as IComponent;
379 return GetComponentInfo (com).GetProperties (attributes);
381 return GetTypeInfo (component.GetType()).GetProperties (attributes);
385 public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
387 return GetProperties (component, null, noCustomTypeDesc);
390 public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
392 return GetTypeInfo (componentType).GetProperties (attributes);
395 public static void SortDescriptorArray (IList infos)
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];
403 Array.Sort (names, values);
405 foreach (object ob in values)
409 public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
410 get { return descriptorHandler; }
411 set { descriptorHandler = value; }
414 public static void Refresh (Assembly assembly)
416 foreach (Type type in assembly.GetTypes())
420 public static void Refresh (Module module)
422 foreach (Type type in module.GetTypes())
426 public static void Refresh (object component)
428 lock (componentTable)
430 componentTable.Remove (component);
432 if (Refreshed != null) Refreshed (new RefreshEventArgs (component));
435 public static void Refresh (Type type)
439 typeTable.Remove (type);
441 if (Refreshed != null) Refreshed (new RefreshEventArgs (type));
444 public static event RefreshEventHandler Refreshed;
446 internal static ComponentInfo GetComponentInfo (IComponent com)
448 lock (componentTable)
450 ComponentInfo ci = (ComponentInfo) componentTable [com];
452 ci = new ComponentInfo (com);
453 componentTable [com] = ci;
459 internal static TypeInfo GetTypeInfo (Type type)
463 TypeInfo ci = (TypeInfo) typeTable [type];
465 ci = new TypeInfo (type);
466 typeTable [type] = ci;
472 static Type GetTypeFromName (IComponent component, string typeName)
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);
479 Type t = Type.GetType (typeName);
480 if (t == null) throw new ArgumentException ("Type '" + typeName + "' not found");
485 internal abstract class Info
488 EventDescriptor _defaultEvent;
489 bool _gotDefaultEvent;
490 PropertyDescriptor _defaultProperty;
491 bool _gotDefaultProperty;
493 public Info (Type infoType)
495 _infoType = infoType;
498 public abstract AttributeCollection GetAttributes ();
499 public abstract EventDescriptorCollection GetEvents ();
500 public abstract PropertyDescriptorCollection GetProperties ();
504 get { return _infoType; }
507 public EventDescriptorCollection GetEvents (Attribute[] attributes)
509 EventDescriptorCollection evs = GetEvents ();
510 if (attributes == null) return evs;
511 else return evs.Filter (attributes);
514 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
516 PropertyDescriptorCollection props = GetProperties ();
517 if (attributes == null) return props;
518 else return props.Filter (attributes);
521 public EventDescriptor GetDefaultEvent ()
523 if (_gotDefaultEvent) return _defaultEvent;
525 DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
526 if (attr == null || attr.Name == null)
527 _defaultEvent = null;
529 EventInfo ei = _infoType.GetEvent (attr.Name);
531 throw new ArgumentException ("Event '" + attr.Name + "' not found in class " + _infoType);
532 _defaultEvent = new ReflectionEventDescriptor (ei);
534 _gotDefaultEvent = true;
535 return _defaultEvent;
538 public PropertyDescriptor GetDefaultProperty ()
540 if (_gotDefaultProperty) return _defaultProperty;
542 DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
543 if (attr == null || attr.Name == null)
544 _defaultProperty = null;
546 PropertyInfo ei = _infoType.GetProperty (attr.Name);
548 throw new ArgumentException ("Property '" + attr.Name + "' not found in class " + _infoType);
549 _defaultProperty = new ReflectionPropertyDescriptor (ei);
551 _gotDefaultProperty = true;
552 return _defaultProperty;
556 internal class ComponentInfo : Info
558 IComponent _component;
559 AttributeCollection _attributes;
560 EventDescriptorCollection _events;
561 PropertyDescriptorCollection _properties;
563 public ComponentInfo (IComponent component): base (component.GetType())
565 _component = component;
568 public override AttributeCollection GetAttributes ()
570 if (_attributes != null) return _attributes;
573 object[] ats = _component.GetType().GetCustomAttributes (true);
574 Hashtable t = new Hashtable ();
575 foreach (Attribute at in ats)
578 if (_component.Site != null)
580 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
581 cache = filter.FilterAttributes (_component, t);
584 ArrayList atts = new ArrayList ();
585 atts.AddRange (t.Values);
586 AttributeCollection attCol = new AttributeCollection (atts);
587 if (cache) _attributes = attCol;
591 public override EventDescriptorCollection GetEvents ()
593 if (_events != null) return _events;
596 EventInfo[] events = _component.GetType().GetEvents ();
597 Hashtable t = new Hashtable ();
598 foreach (EventInfo ev in events)
599 t [ev.Name] = new ReflectionEventDescriptor (ev);
601 if (_component.Site != null)
603 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
604 cache = filter.FilterEvents (_component, t);
607 ArrayList atts = new ArrayList ();
608 atts.AddRange (t.Values);
609 EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
610 if (cache) _events = attCol;
614 public override PropertyDescriptorCollection GetProperties ()
616 if (_properties != null) return _properties;
619 PropertyInfo[] props = _component.GetType().GetProperties ();
620 Hashtable t = new Hashtable ();
621 foreach (PropertyInfo pr in props)
622 t [pr.Name] = new ReflectionPropertyDescriptor (pr);
624 if (_component.Site != null)
626 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
627 cache = filter.FilterProperties (_component, t);
630 ArrayList atts = new ArrayList ();
631 atts.AddRange (t.Values);
632 PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (atts);
633 if (cache) _properties = attCol;
638 internal class TypeInfo : Info
640 AttributeCollection _attributes;
641 EventDescriptorCollection _events;
642 PropertyDescriptorCollection _properties;
644 public TypeInfo (Type t): base (t)
648 public override AttributeCollection GetAttributes ()
650 if (_attributes != null) return _attributes;
652 object[] atts = InfoType.GetCustomAttributes (true);
653 _attributes = new AttributeCollection ((Attribute[]) atts);
657 public override EventDescriptorCollection GetEvents ()
659 if (_events != null) return _events;
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]);
666 _events = new EventDescriptorCollection (descs);
670 public override PropertyDescriptorCollection GetProperties ()
672 if (_properties != null) return _properties;
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]);
679 _properties = new PropertyDescriptorCollection (descs);