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 // 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:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
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.
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 object creatingDefaultConverters = new object ();
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 ()
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));
75 public static EventDescriptor CreateEvent (Type componentType,
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,
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 ();
126 IComponent com = component as IComponent;
127 if (com != null && com.Site != null)
128 return GetComponentInfo (com).GetAttributes ();
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 String res = ((ICustomTypeDescriptor) component).GetClassName ();
147 res = ((ICustomTypeDescriptor) component).GetComponentName ();
149 res = component.GetType ().FullName;
152 return component.GetType ().FullName;
156 public static string GetComponentName (object component)
158 return GetComponentName (component, false);
161 public static string GetComponentName (object component, bool noCustomTypeDesc)
163 if (component == null)
164 throw new ArgumentNullException ("component", "component cannot be null");
166 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
167 return ((ICustomTypeDescriptor) component).GetComponentName ();
169 IComponent c = component as IComponent;
170 if (c != null && c.Site != null)
175 return component.GetType().Name;
180 public static TypeConverter GetConverter (object component)
182 return GetConverter (component, false);
185 public static TypeConverter GetConverter (object component, bool noCustomTypeDesc)
187 if (component == null)
188 throw new ArgumentNullException ("component", "component cannot be null");
190 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
191 return ((ICustomTypeDescriptor) component).GetConverter ();
195 AttributeCollection atts = GetAttributes (component, false);
196 TypeConverterAttribute tca = (TypeConverterAttribute) atts[typeof(TypeConverterAttribute)];
197 if (tca != null && tca.ConverterTypeName.Length > 0) {
198 t = GetTypeFromName (component as IComponent, tca.ConverterTypeName);
202 ConstructorInfo ci = t.GetConstructor (new Type[] { typeof(Type) });
204 return (TypeConverter) ci.Invoke (new object[] { component.GetType () });
206 return (TypeConverter) Activator.CreateInstance (t);
209 return GetConverter (component.GetType ());
213 private static Hashtable DefaultConverters
216 lock (creatingDefaultConverters) {
217 if (defaultConverters != null)
218 return defaultConverters;
220 defaultConverters = new Hashtable ();
221 defaultConverters.Add (typeof (bool), typeof (BooleanConverter));
222 defaultConverters.Add (typeof (byte), typeof (ByteConverter));
223 defaultConverters.Add (typeof (sbyte), typeof (SByteConverter));
224 defaultConverters.Add (typeof (string), typeof (StringConverter));
225 defaultConverters.Add (typeof (char), typeof (CharConverter));
226 defaultConverters.Add (typeof (short), typeof (Int16Converter));
227 defaultConverters.Add (typeof (int), typeof (Int32Converter));
228 defaultConverters.Add (typeof (long), typeof (Int64Converter));
229 defaultConverters.Add (typeof (ushort), typeof (UInt16Converter));
230 defaultConverters.Add (typeof (uint), typeof (UInt32Converter));
231 defaultConverters.Add (typeof (ulong), typeof (UInt64Converter));
232 defaultConverters.Add (typeof (float), typeof (SingleConverter));
233 defaultConverters.Add (typeof (double), typeof (DoubleConverter));
234 defaultConverters.Add (typeof (decimal), typeof (DecimalConverter));
235 defaultConverters.Add (typeof (object), typeof (TypeConverter));
236 defaultConverters.Add (typeof (void), typeof (TypeConverter));
237 defaultConverters.Add (typeof (Array), typeof (ArrayConverter));
238 defaultConverters.Add (typeof (CultureInfo), typeof (CultureInfoConverter));
239 defaultConverters.Add (typeof (DateTime), typeof (DateTimeConverter));
240 defaultConverters.Add (typeof (Guid), typeof (GuidConverter));
241 defaultConverters.Add (typeof (TimeSpan), typeof (TimeSpanConverter));
242 defaultConverters.Add (typeof (ICollection), typeof (CollectionConverter));
244 return defaultConverters;
248 public static TypeConverter GetConverter (Type type)
250 TypeConverterAttribute tca = null;
252 object [] atts = type.GetCustomAttributes (typeof(TypeConverterAttribute), true);
255 tca = (TypeConverterAttribute)atts[0];
258 t = GetTypeFromName (null, tca.ConverterTypeName);
263 // EnumConverter needs to know the enum type
264 return new EnumConverter(type);
265 } else if (type.IsArray) {
266 return new ArrayConverter ();
271 t = FindConverterType (type);
274 Exception exc = null;
276 return (TypeConverter) Activator.CreateInstance (t);
277 } catch (MissingMethodException e) {
282 return (TypeConverter) Activator.CreateInstance (t, new object [] {type});
283 } catch (MissingMethodException e) {
288 return new ReferenceConverter (type); // Default?
291 private static Type FindConverterType (Type type)
295 // Is there a default converter
296 t = (Type) DefaultConverters [type];
300 // Find default converter with a type this type is assignable to
301 foreach (Type defType in DefaultConverters.Keys) {
302 if (defType.IsInterface && defType.IsAssignableFrom (type)) {
303 return (Type) DefaultConverters [defType];
307 // Nothing found, try the same with our base type
308 if (type.BaseType != null)
309 return FindConverterType (type.BaseType);
314 public static EventDescriptor GetDefaultEvent (Type componentType)
316 return GetTypeInfo (componentType).GetDefaultEvent ();
319 public static EventDescriptor GetDefaultEvent (object component)
321 return GetDefaultEvent (component, false);
324 public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
326 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
327 return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
329 IComponent com = component as IComponent;
330 if (com != null && com.Site != null)
331 return GetComponentInfo (com).GetDefaultEvent ();
333 return GetTypeInfo (component.GetType()).GetDefaultEvent ();
337 public static PropertyDescriptor GetDefaultProperty (Type componentType)
339 return GetTypeInfo (componentType).GetDefaultProperty ();
342 public static PropertyDescriptor GetDefaultProperty (object component)
344 return GetDefaultProperty (component, false);
347 public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
349 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
350 return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
352 IComponent com = component as IComponent;
353 if (com != null && com.Site != null)
354 return GetComponentInfo (com).GetDefaultProperty ();
356 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
360 public static object GetEditor (Type componentType, Type editorBaseType)
363 object [] atts = componentType.GetCustomAttributes (typeof(EditorAttribute), true);
364 if (atts == null || atts.Length == 0)
368 foreach (EditorAttribute ea in atts)
370 t = GetTypeFromName (null, ea.EditorTypeName);
371 if (t.IsSubclassOf(editorBaseType))
376 Exception exc = null;
378 return Activator.CreateInstance (t);
379 } catch (MissingMethodException e) {
384 return Activator.CreateInstance (t, new object [] {componentType});
385 } catch (MissingMethodException e) {
390 return null; // No editor specified
393 public static object GetEditor (object component, Type editorBaseType)
395 return GetEditor (component, editorBaseType, false);
399 public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
401 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
402 return ((ICustomTypeDescriptor) component).GetEditor (editorBaseType);
403 throw new NotImplementedException ();
406 public static EventDescriptorCollection GetEvents (object component)
408 return GetEvents (component, false);
411 public static EventDescriptorCollection GetEvents (Type componentType)
413 return GetEvents (componentType, null);
416 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes)
418 return GetEvents (component, attributes, false);
421 public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
423 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
424 return ((ICustomTypeDescriptor) component).GetEvents ();
426 IComponent com = component as IComponent;
427 if (com != null && com.Site != null)
428 return GetComponentInfo (com).GetEvents ();
430 return GetTypeInfo (component.GetType()).GetEvents ();
434 public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
436 return GetTypeInfo (componentType).GetEvents (attributes);
439 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
441 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
442 return ((ICustomTypeDescriptor) component).GetEvents (attributes);
444 IComponent com = component as IComponent;
445 if (com != null && com.Site != null)
446 return GetComponentInfo (com).GetEvents (attributes);
448 return GetTypeInfo (component.GetType()).GetEvents (attributes);
452 public static PropertyDescriptorCollection GetProperties (object component)
454 return GetProperties (component, false);
457 public static PropertyDescriptorCollection GetProperties (Type componentType)
459 return GetProperties (componentType, null);
462 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes)
464 return GetProperties (component, attributes, false);
467 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
469 if (component == null)
470 return PropertyDescriptorCollection.Empty;
472 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
473 return ((ICustomTypeDescriptor) component).GetProperties (attributes);
475 IComponent com = component as IComponent;
476 if (com != null && com.Site != null)
477 return GetComponentInfo (com).GetProperties (attributes);
479 return GetTypeInfo (component.GetType()).GetProperties (attributes);
483 public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
485 if (component == null)
486 return PropertyDescriptorCollection.Empty;
488 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
489 return ((ICustomTypeDescriptor) component).GetProperties ();
491 IComponent com = component as IComponent;
492 if (com != null && com.Site != null)
493 return GetComponentInfo (com).GetProperties ();
495 return GetTypeInfo (component.GetType()).GetProperties ();
499 public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
501 return GetTypeInfo (componentType).GetProperties (attributes);
504 public static void SortDescriptorArray (IList infos)
506 string[] names = new string [infos.Count];
507 object[] values = new object [infos.Count];
508 for (int n=0; n<names.Length; n++) {
509 names[n] = ((MemberDescriptor)infos[n]).Name;
510 values[n] = infos[n];
512 Array.Sort (names, values);
514 foreach (object ob in values)
518 public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
519 get { return descriptorHandler; }
520 set { descriptorHandler = value; }
523 public static void Refresh (Assembly assembly)
525 foreach (Type type in assembly.GetTypes())
529 public static void Refresh (Module module)
531 foreach (Type type in module.GetTypes())
535 public static void Refresh (object component)
537 lock (componentTable)
539 componentTable.Remove (component);
541 if (Refreshed != null) Refreshed (new RefreshEventArgs (component));
544 public static void Refresh (Type type)
548 typeTable.Remove (type);
550 if (Refreshed != null) Refreshed (new RefreshEventArgs (type));
553 static EventHandler onDispose;
555 static void OnComponentDisposed (object sender, EventArgs args)
557 lock (componentTable) {
558 componentTable.Remove (sender);
562 public static event RefreshEventHandler Refreshed;
564 internal static ComponentInfo GetComponentInfo (IComponent com)
566 lock (componentTable)
568 ComponentInfo ci = (ComponentInfo) componentTable [com];
570 if (onDispose == null)
571 onDispose = new EventHandler (OnComponentDisposed);
573 com.Disposed += onDispose;
574 ci = new ComponentInfo (com);
575 componentTable [com] = ci;
581 internal static TypeInfo GetTypeInfo (Type type)
585 TypeInfo ci = (TypeInfo) typeTable [type];
587 ci = new TypeInfo (type);
588 typeTable [type] = ci;
594 static Type GetTypeFromName (IComponent component, string typeName)
596 if (component != null && component.Site != null) {
597 ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
599 return resver.GetType (typeName, true, false);
602 Type t = Type.GetType (typeName);
603 if (t == null) throw new ArgumentException ("Type '" + typeName + "' not found");
608 internal abstract class Info
611 EventDescriptor _defaultEvent;
612 bool _gotDefaultEvent;
613 PropertyDescriptor _defaultProperty;
614 bool _gotDefaultProperty;
615 AttributeCollection _attributes;
617 public Info (Type infoType)
619 _infoType = infoType;
622 public abstract AttributeCollection GetAttributes ();
623 public abstract EventDescriptorCollection GetEvents ();
624 public abstract PropertyDescriptorCollection GetProperties ();
628 get { return _infoType; }
631 public EventDescriptorCollection GetEvents (Attribute[] attributes)
633 EventDescriptorCollection evs = GetEvents ();
634 if (attributes == null)
637 return evs.Filter (attributes);
640 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
642 PropertyDescriptorCollection props = GetProperties ();
643 if (attributes == null)
646 return props.Filter (attributes);
649 public EventDescriptor GetDefaultEvent ()
651 if (_gotDefaultEvent)
652 return _defaultEvent;
654 DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
655 if (attr == null || attr.Name == null)
656 _defaultEvent = null;
658 EventDescriptorCollection events = GetEvents ();
659 _defaultEvent = events [attr.Name];
661 // In our test case (TypeDescriptorTest.TestGetDefaultEvent), we have
662 // a scenario where a custom filter adds the DefaultEventAttribute,
663 // but its FilterEvents method removes the event the
664 // DefaultEventAttribute applied to. .NET 1.x accepts this and returns
665 // the *other* event defined in the class.
667 // Consequently, we know we have a DefaultEvent, but we need to check
668 // and ensure that the requested event is unfiltered. If it is, just
669 // grab the first element in the collection.
670 if (_defaultEvent == null && events.Count > 0)
671 _defaultEvent = events [0];
674 _gotDefaultEvent = true;
675 return _defaultEvent;
678 public PropertyDescriptor GetDefaultProperty ()
680 if (_gotDefaultProperty)
681 return _defaultProperty;
683 DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
684 if (attr == null || attr.Name == null)
685 _defaultProperty = null;
687 PropertyDescriptorCollection properties = GetProperties ();
688 _defaultProperty = properties[attr.Name];
690 _gotDefaultProperty = true;
691 return _defaultProperty;
694 protected AttributeCollection GetAttributes (IComponent comp)
696 if (_attributes != null)
700 object[] ats = _infoType.GetCustomAttributes (true);
701 Hashtable t = new Hashtable ();
702 foreach (Attribute at in ats)
705 if (comp != null && comp.Site != null)
707 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) comp.Site.GetService (typeof(ITypeDescriptorFilterService));
708 cache = filter.FilterAttributes (comp, t);
711 ArrayList atts = new ArrayList ();
712 atts.AddRange (t.Values);
713 AttributeCollection attCol = new AttributeCollection (atts);
715 _attributes = attCol;
720 internal class ComponentInfo : Info
722 IComponent _component;
723 EventDescriptorCollection _events;
724 PropertyDescriptorCollection _properties;
726 public ComponentInfo (IComponent component): base (component.GetType())
728 _component = component;
731 public override AttributeCollection GetAttributes ()
733 return base.GetAttributes (_component);
736 public override EventDescriptorCollection GetEvents ()
742 EventInfo[] events = _component.GetType().GetEvents ();
743 Hashtable t = new Hashtable ();
744 foreach (EventInfo ev in events)
745 t [ev.Name] = new ReflectionEventDescriptor (ev);
747 if (_component.Site != null)
749 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
750 cache = filter.FilterEvents (_component, t);
753 ArrayList atts = new ArrayList ();
754 atts.AddRange (t.Values);
755 EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
756 if (cache) _events = attCol;
760 public override PropertyDescriptorCollection GetProperties ()
762 if (_properties != null)
766 Console.WriteLine ("Here");
767 PropertyInfo[] props = _component.GetType().GetProperties (BindingFlags.Instance | BindingFlags.Public);
768 Hashtable t = new Hashtable ();
769 foreach (PropertyInfo pr in props)
770 t [pr.Name] = new ReflectionPropertyDescriptor (pr);
772 if (_component.Site != null)
774 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
775 cache = filter.FilterProperties (_component, t);
778 PropertyDescriptor[] descriptors = new PropertyDescriptor[t.Values.Count];
779 t.Values.CopyTo (descriptors, 0);
780 PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (descriptors, true);
782 _properties = attCol;
787 internal class TypeInfo : Info
789 EventDescriptorCollection _events;
790 PropertyDescriptorCollection _properties;
792 public TypeInfo (Type t): base (t)
796 public override AttributeCollection GetAttributes ()
798 return base.GetAttributes (null);
801 public override EventDescriptorCollection GetEvents ()
806 EventInfo[] events = InfoType.GetEvents ();
807 EventDescriptor[] descs = new EventDescriptor [events.Length];
808 for (int n=0; n<events.Length; n++)
809 descs [n] = new ReflectionEventDescriptor (events[n]);
811 _events = new EventDescriptorCollection (descs);
815 public override PropertyDescriptorCollection GetProperties ()
817 if (_properties != null)
820 PropertyInfo[] props = InfoType.GetProperties (BindingFlags.Instance | BindingFlags.Public);
821 PropertyDescriptor[] descs = new PropertyDescriptor [props.Length];
822 for (int n=0; n<props.Length; n++)
823 descs [n] = new ReflectionPropertyDescriptor (props[n]);
825 _properties = new PropertyDescriptorCollection (descs, true);