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 if (((IComponent
) component
).Site
== null)
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 ();
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
];
196 primitive
= primitive
.BaseType
;
200 return (TypeConverter
) Activator
.CreateInstance (t
);
206 private static Hashtable DefaultConverters
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
)
249 // EnumConverter needs to know the enum type
250 return new EnumConverter(type
);
252 TypeConverterAttribute tca
= null;
254 object [] atts
= type
.GetCustomAttributes (typeof(TypeConverterAttribute
), true);
257 tca
= (TypeConverterAttribute
)atts
[0];
260 t
= GetTypeFromName (null, tca
.ConverterTypeName
);
263 Type primitive
= type
;
264 while (t
== null && primitive
!= typeof (object)) {
265 t
= (Type
) DefaultConverters
[primitive
];
267 primitive
= primitive
.BaseType
;
271 return (TypeConverter
) Activator
.CreateInstance (t
);
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 ();
292 IComponent com
= component
as IComponent
;
294 return GetComponentInfo (com
).GetDefaultEvent ();
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 ();
315 IComponent com
= component
as IComponent
;
317 return GetComponentInfo (com
).GetDefaultProperty ();
319 return GetTypeInfo (component
.GetType()).GetDefaultProperty ();
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);
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
);
370 IComponent com
= component
as IComponent
;
372 return GetComponentInfo (com
).GetEvents (attributes
);
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
);
398 IComponent com
= component
as IComponent
;
400 return GetComponentInfo (com
).GetProperties (attributes
);
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
);
426 foreach (object ob
in values
)
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())
441 public static void Refresh (Module module
)
443 foreach (Type type
in module
.GetTypes())
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
)
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
];
482 if (onDispose
== null)
483 onDispose
= new EventHandler (OnComponentDisposed
);
485 com
.Disposed
+= onDispose
;
486 ci
= new ComponentInfo (com
);
487 componentTable
[com
] = ci
;
493 internal static TypeInfo
GetTypeInfo (Type type
)
497 TypeInfo ci
= (TypeInfo
) typeTable
[type
];
499 ci
= new TypeInfo (type
);
500 typeTable
[type
] = 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");
519 internal abstract class Info
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 ();
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;
564 EventInfo ei
= _infoType
.GetEvent (attr
.Name
);
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;
581 PropertyInfo ei
= _infoType
.GetProperty (attr
.Name
);
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
;
595 object[] ats
= _infoType
.GetCustomAttributes (true);
596 Hashtable t
= new Hashtable ();
597 foreach (Attribute at
in ats
)
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
;
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
;
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
;
653 public override PropertyDescriptorCollection
GetProperties ()
655 if (_properties
!= null) return _properties
;
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
;
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
);
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
);