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 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 ()
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;
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 return ((ICustomTypeDescriptor) component).GetClassName ();
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 ();
164 IComponent c = component as IComponent;
165 if (c != null && c.Site != null)
167 return component.GetType().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 ();
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);
193 return (TypeConverter) Activator.CreateInstance (t);
195 return GetConverter (component.GetType ());
199 private static Hashtable DefaultConverters
202 if (defaultConverters != null)
203 return defaultConverters;
205 lock (creatingDefaultConverters) {
206 if (defaultConverters != null)
207 return defaultConverters;
209 defaultConverters = new Hashtable ();
210 defaultConverters.Add (typeof (bool), typeof (BooleanConverter));
211 defaultConverters.Add (typeof (byte), typeof (ByteConverter));
212 defaultConverters.Add (typeof (sbyte), typeof (SByteConverter));
213 defaultConverters.Add (typeof (string), typeof (StringConverter));
214 defaultConverters.Add (typeof (char), typeof (CharConverter));
215 defaultConverters.Add (typeof (short), typeof (Int16Converter));
216 defaultConverters.Add (typeof (int), typeof (Int32Converter));
217 defaultConverters.Add (typeof (long), typeof (Int64Converter));
218 defaultConverters.Add (typeof (ushort), typeof (UInt16Converter));
219 defaultConverters.Add (typeof (uint), typeof (UInt32Converter));
220 defaultConverters.Add (typeof (ulong), typeof (UInt64Converter));
221 defaultConverters.Add (typeof (float), typeof (SingleConverter));
222 defaultConverters.Add (typeof (double), typeof (DoubleConverter));
223 defaultConverters.Add (typeof (decimal), typeof (DecimalConverter));
224 defaultConverters.Add (typeof (object), typeof (TypeConverter));
225 defaultConverters.Add (typeof (void), typeof (TypeConverter));
226 defaultConverters.Add (typeof (Array), typeof (ArrayConverter));
227 defaultConverters.Add (typeof (CultureInfo), typeof (CultureInfoConverter));
228 defaultConverters.Add (typeof (DateTime), typeof (DateTimeConverter));
229 defaultConverters.Add (typeof (Guid), typeof (GuidConverter));
230 defaultConverters.Add (typeof (TimeSpan), typeof (TimeSpanConverter));
231 defaultConverters.Add (typeof (ICollection), typeof (CollectionConverter));
233 return defaultConverters;
237 public static TypeConverter GetConverter (Type type)
239 TypeConverterAttribute tca = null;
241 object [] atts = type.GetCustomAttributes (typeof(TypeConverterAttribute), true);
244 tca = (TypeConverterAttribute)atts[0];
247 t = GetTypeFromName (null, tca.ConverterTypeName);
252 // EnumConverter needs to know the enum type
253 return new EnumConverter(type);
254 } else if (type.IsArray) {
255 return new ArrayConverter ();
260 t = FindConverterType (type);
\r
263 return (TypeConverter) Activator.CreateInstance (t);
265 return new ReferenceConverter (type); // Default?
268 private static Type FindConverterType (Type type)
\r
272 // Is there a default converter
\r
273 t = (Type) DefaultConverters [type];
\r
277 // Find default converter with a type this type is assignable to
\r
278 foreach (Type defType in DefaultConverters.Keys) {
\r
279 if (defType.IsInterface && defType.IsAssignableFrom (type)) {
\r
280 return (Type) DefaultConverters [defType];
\r
284 // Nothing found, try the same with our base type
\r
285 if (type.BaseType != null)
\r
286 return FindConverterType (type.BaseType);
\r
291 public static EventDescriptor GetDefaultEvent (Type componentType)
293 return GetTypeInfo (componentType).GetDefaultEvent ();
296 public static EventDescriptor GetDefaultEvent (object component)
298 return GetDefaultEvent (component, false);
301 public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
303 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
304 return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
306 IComponent com = component as IComponent;
308 return GetComponentInfo (com).GetDefaultEvent ();
310 return GetTypeInfo (component.GetType()).GetDefaultEvent ();
314 public static PropertyDescriptor GetDefaultProperty (Type componentType)
316 return GetTypeInfo (componentType).GetDefaultProperty ();
319 public static PropertyDescriptor GetDefaultProperty (object component)
321 return GetDefaultProperty (component, false);
324 public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
326 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
327 return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
329 IComponent com = component as IComponent;
331 return GetComponentInfo (com).GetDefaultProperty ();
333 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
338 public static object GetEditor (Type componentType, Type editorBaseType)
340 throw new NotImplementedException ();
343 public static object GetEditor (object component, Type editorBaseType)
345 return GetEditor (component, editorBaseType, false);
349 public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
351 throw new NotImplementedException ();
354 public static EventDescriptorCollection GetEvents (object component)
356 return GetEvents (component, false);
359 public static EventDescriptorCollection GetEvents (Type componentType)
361 return GetEvents (componentType, null);
364 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes)
366 return GetEvents (component, attributes, false);
369 public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
371 return GetEvents (component, null, noCustomTypeDesc);
374 public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
376 return GetTypeInfo (componentType).GetEvents (attributes);
379 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
381 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
382 return ((ICustomTypeDescriptor) component).GetEvents (attributes);
384 IComponent com = component as IComponent;
386 return GetComponentInfo (com).GetEvents (attributes);
388 return GetTypeInfo (component.GetType()).GetEvents (attributes);
392 public static PropertyDescriptorCollection GetProperties (object component)
394 return GetProperties (component, false);
397 public static PropertyDescriptorCollection GetProperties (Type componentType)
399 return GetProperties (componentType, null);
402 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes)
404 return GetProperties (component, attributes, false);
407 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
409 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
410 return ((ICustomTypeDescriptor) component).GetProperties (attributes);
412 IComponent com = component as IComponent;
414 return GetComponentInfo (com).GetProperties (attributes);
416 return GetTypeInfo (component.GetType()).GetProperties (attributes);
420 public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
422 return GetProperties (component, null, noCustomTypeDesc);
425 public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
427 return GetTypeInfo (componentType).GetProperties (attributes);
430 public static void SortDescriptorArray (IList infos)
432 string[] names = new string [infos.Count];
433 object[] values = new object [infos.Count];
434 for (int n=0; n<names.Length; n++) {
435 names[n] = ((MemberDescriptor)infos[n]).Name;
436 values[n] = infos[n];
438 Array.Sort (names, values);
440 foreach (object ob in values)
444 public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
445 get { return descriptorHandler; }
446 set { descriptorHandler = value; }
449 public static void Refresh (Assembly assembly)
451 foreach (Type type in assembly.GetTypes())
455 public static void Refresh (Module module)
457 foreach (Type type in module.GetTypes())
461 public static void Refresh (object component)
463 lock (componentTable)
465 componentTable.Remove (component);
467 if (Refreshed != null) Refreshed (new RefreshEventArgs (component));
470 public static void Refresh (Type type)
474 typeTable.Remove (type);
476 if (Refreshed != null) Refreshed (new RefreshEventArgs (type));
479 static EventHandler onDispose;
481 static void OnComponentDisposed (object sender, EventArgs args)
483 lock (componentTable) {
484 componentTable.Remove (sender);
488 public static event RefreshEventHandler Refreshed;
490 internal static ComponentInfo GetComponentInfo (IComponent com)
492 lock (componentTable)
494 ComponentInfo ci = (ComponentInfo) componentTable [com];
496 if (onDispose == null)
497 onDispose = new EventHandler (OnComponentDisposed);
499 com.Disposed += onDispose;
500 ci = new ComponentInfo (com);
501 componentTable [com] = ci;
507 internal static TypeInfo GetTypeInfo (Type type)
511 TypeInfo ci = (TypeInfo) typeTable [type];
513 ci = new TypeInfo (type);
514 typeTable [type] = ci;
520 static Type GetTypeFromName (IComponent component, string typeName)
522 if (component != null && component.Site != null) {
523 ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
524 if (resver != null) return resver.GetType (typeName, true, false);
527 Type t = Type.GetType (typeName);
528 if (t == null) throw new ArgumentException ("Type '" + typeName + "' not found");
533 internal abstract class Info
536 EventDescriptor _defaultEvent;
537 bool _gotDefaultEvent;
538 PropertyDescriptor _defaultProperty;
539 bool _gotDefaultProperty;
540 AttributeCollection _attributes;
542 public Info (Type infoType)
544 _infoType = infoType;
547 public abstract AttributeCollection GetAttributes ();
548 public abstract EventDescriptorCollection GetEvents ();
549 public abstract PropertyDescriptorCollection GetProperties ();
553 get { return _infoType; }
556 public EventDescriptorCollection GetEvents (Attribute[] attributes)
558 EventDescriptorCollection evs = GetEvents ();
559 if (attributes == null) return evs;
560 else return evs.Filter (attributes);
563 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
565 PropertyDescriptorCollection props = GetProperties ();
566 if (attributes == null) return props;
567 else return props.Filter (attributes);
570 public EventDescriptor GetDefaultEvent ()
572 if (_gotDefaultEvent) return _defaultEvent;
574 DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
575 if (attr == null || attr.Name == null)
576 _defaultEvent = null;
579 // In our test case (TypeDescriptorTest.TestGetDefaultEvent), we have
580 // a scenario where a custom filter adds the DefaultEventAttribute,
581 // but its FilterEvents method removes the event the
582 // DefaultEventAttribute applied to. .NET accepts this and returns
583 // the *other* event defined in the class.
585 // Consequently, we know we have a DefaultEvent, but we need to check
586 // and ensure that the requested event is unfiltered. If it is, just
587 // grab the first element in the collection.
588 EventDescriptorCollection events = GetEvents ();
589 _defaultEvent = events [attr.Name];
590 if (_defaultEvent == null && events.Count > 0)
591 _defaultEvent = events [0];
593 _gotDefaultEvent = true;
594 return _defaultEvent;
597 public PropertyDescriptor GetDefaultProperty ()
599 if (_gotDefaultProperty) return _defaultProperty;
601 DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
602 if (attr == null || attr.Name == null)
603 _defaultProperty = null;
605 PropertyInfo ei = _infoType.GetProperty (attr.Name);
607 throw new ArgumentException ("Property '" + attr.Name + "' not found in class " + _infoType);
608 _defaultProperty = new ReflectionPropertyDescriptor (ei);
610 _gotDefaultProperty = true;
611 return _defaultProperty;
614 protected AttributeCollection GetAttributes (IComponent comp)
616 if (_attributes != null) return _attributes;
619 object[] ats = _infoType.GetCustomAttributes (true);
620 Hashtable t = new Hashtable ();
621 foreach (Attribute at in ats)
624 if (comp != null && comp.Site != null)
626 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) comp.Site.GetService (typeof(ITypeDescriptorFilterService));
627 cache = filter.FilterAttributes (comp, t);
630 ArrayList atts = new ArrayList ();
631 atts.AddRange (t.Values);
632 AttributeCollection attCol = new AttributeCollection (atts);
633 if (cache) _attributes = attCol;
638 internal class ComponentInfo : Info
640 IComponent _component;
641 EventDescriptorCollection _events;
642 PropertyDescriptorCollection _properties;
644 public ComponentInfo (IComponent component): base (component.GetType())
646 _component = component;
649 public override AttributeCollection GetAttributes ()
651 return base.GetAttributes (_component);
654 public override EventDescriptorCollection GetEvents ()
656 if (_events != null) return _events;
659 EventInfo[] events = _component.GetType().GetEvents ();
660 Hashtable t = new Hashtable ();
661 foreach (EventInfo ev in events)
662 t [ev.Name] = new ReflectionEventDescriptor (ev);
664 if (_component.Site != null)
666 Console.WriteLine ("filtering events...");
667 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
668 cache = filter.FilterEvents (_component, t);
671 ArrayList atts = new ArrayList ();
672 atts.AddRange (t.Values);
673 EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
674 if (cache) _events = attCol;
678 public override PropertyDescriptorCollection GetProperties ()
680 if (_properties != null) return _properties;
683 PropertyInfo[] props = _component.GetType().GetProperties ();
684 Hashtable t = new Hashtable ();
685 foreach (PropertyInfo pr in props)
686 t [pr.Name] = new ReflectionPropertyDescriptor (pr);
688 if (_component.Site != null)
690 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
691 cache = filter.FilterProperties (_component, t);
694 ArrayList atts = new ArrayList ();
695 atts.AddRange (t.Values);
696 PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (atts);
697 if (cache) _properties = attCol;
702 internal class TypeInfo : Info
704 EventDescriptorCollection _events;
705 PropertyDescriptorCollection _properties;
707 public TypeInfo (Type t): base (t)
711 public override AttributeCollection GetAttributes ()
713 return base.GetAttributes (null);
716 public override EventDescriptorCollection GetEvents ()
718 if (_events != null) return _events;
720 EventInfo[] events = InfoType.GetEvents ();
721 EventDescriptor[] descs = new EventDescriptor [events.Length];
722 for (int n=0; n<events.Length; n++)
723 descs [n] = new ReflectionEventDescriptor (events[n]);
725 _events = new EventDescriptorCollection (descs);
729 public override PropertyDescriptorCollection GetProperties ()
731 if (_properties != null) return _properties;
733 PropertyInfo[] props = InfoType.GetProperties ();
734 PropertyDescriptor[] descs = new PropertyDescriptor [props.Length];
735 for (int n=0; n<props.Length; n++)
736 descs [n] = new ReflectionPropertyDescriptor (props[n]);
738 _properties = new PropertyDescriptorCollection (descs);