2 // System.ComponentModel.TypeDescriptor.cs
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 // Ivan N. Zlatev (contact@i-nz.net)
10 // (C) 2002 Ximian, Inc (http://www.ximian.com)
11 // (C) 2003 Andreas Nahr
12 // (C) 2008 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System
.Collections
;
37 using System
.Reflection
;
38 using System
.Globalization
;
39 using System
.ComponentModel
.Design
;
40 using System
.Security
.Permissions
;
43 using System
.Collections
.Generic
;
46 namespace System
.ComponentModel
49 public sealed class TypeDescriptor
51 private static readonly object creatingDefaultConverters
= new object ();
52 private static ArrayList defaultConverters
;
53 private static IComNativeDescriptorHandler descriptorHandler
;
54 private static Hashtable componentTable
= new Hashtable ();
55 private static Hashtable typeTable
= new Hashtable ();
56 private static Hashtable editors
;
59 static object typeDescriptionProvidersLock
= new object ();
60 static Dictionary
<Type
, LinkedList
<TypeDescriptionProvider
>> typeDescriptionProviders
;
62 static object componentDescriptionProvidersLock
= new object ();
63 static Dictionary
<WeakObjectWrapper
, LinkedList
<TypeDescriptionProvider
>> componentDescriptionProviders
;
65 static TypeDescriptor ()
67 typeDescriptionProviders
= new Dictionary
<Type
, LinkedList
<TypeDescriptionProvider
>> ();
68 componentDescriptionProviders
= new Dictionary
<WeakObjectWrapper
, LinkedList
<TypeDescriptionProvider
>> (new WeakObjectWrapperComparer ());
71 private TypeDescriptor ()
76 [MonoNotSupported ("Mono does not support COM")]
77 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
78 public static Type ComObjectType
{
79 get { throw new NotImplementedException (); }
82 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
83 public static TypeDescriptionProvider
AddAttributes (object instance
, params Attribute
[] attributes
)
86 throw new ArgumentNullException ("instance");
87 if (attributes
== null)
88 throw new ArgumentNullException ("attributes");
90 var ret
= new AttributeProvider (attributes
, GetProvider (instance
));
91 AddProvider (ret
, instance
);
96 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
97 public static TypeDescriptionProvider
AddAttributes (Type type
, params Attribute
[] attributes
)
100 throw new ArgumentNullException ("type");
101 if (attributes
== null)
102 throw new ArgumentNullException ("attributes");
104 var ret
= new AttributeProvider (attributes
, GetProvider (type
));
105 AddProvider (ret
, type
);
110 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
111 public static void AddProvider (TypeDescriptionProvider provider
, object instance
)
113 if (provider
== null)
114 throw new ArgumentNullException ("provider");
115 if (instance
== null)
116 throw new ArgumentNullException ("instance");
118 lock (componentDescriptionProvidersLock
) {
119 LinkedList
<TypeDescriptionProvider
> plist
;
120 WeakObjectWrapper instanceWrapper
= new WeakObjectWrapper (instance
);
122 if (!componentDescriptionProviders
.TryGetValue (instanceWrapper
, out plist
)) {
123 plist
= new LinkedList
<TypeDescriptionProvider
> ();
124 componentDescriptionProviders
.Add (new WeakObjectWrapper (instance
), plist
);
127 plist
.AddLast (provider
);
128 instanceWrapper
= null;
133 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
134 public static void AddProvider (TypeDescriptionProvider provider
, Type type
)
136 if (provider
== null)
137 throw new ArgumentNullException ("provider");
139 throw new ArgumentNullException ("type");
141 lock (typeDescriptionProvidersLock
) {
142 LinkedList
<TypeDescriptionProvider
> plist
;
144 if (!typeDescriptionProviders
.TryGetValue (type
, out plist
)) {
145 plist
= new LinkedList
<TypeDescriptionProvider
> ();
146 typeDescriptionProviders
.Add (type
, plist
);
149 plist
.AddLast (provider
);
155 public static object CreateInstance (IServiceProvider provider
, Type objectType
, Type
[] argTypes
, object [] args
)
157 if (objectType
== null)
158 throw new ArgumentNullException ("objectType");
160 object instance
= null;
162 if (provider
!= null) {
163 TypeDescriptionProvider typeDescrProvider
= provider
.GetService (typeof (TypeDescriptionProvider
)) as TypeDescriptionProvider
;
164 if (typeDescrProvider
!= null)
165 instance
= typeDescrProvider
.CreateInstance (provider
, objectType
, argTypes
, args
);
168 // TODO: also search and use the internal providers table once Add/RemoveProvider have been implemented
170 if (instance
== null)
171 instance
= Activator
.CreateInstance (objectType
, args
);
178 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
185 static void AddEditorTable (Type editorBaseType
, Hashtable table
)
187 if (editorBaseType
== null)
188 throw new ArgumentNullException ("editorBaseType");
191 editors
= new Hashtable ();
193 if (!editors
.ContainsKey (editorBaseType
))
194 editors
[editorBaseType
] = table
;
197 public static IDesigner
CreateDesigner(IComponent component
, Type designerBaseType
)
199 string tn
= designerBaseType
.AssemblyQualifiedName
;
200 AttributeCollection col
= GetAttributes (component
);
202 foreach (Attribute at
in col
) {
203 DesignerAttribute dat
= at
as DesignerAttribute
;
204 if (dat
!= null && tn
== dat
.DesignerBaseTypeName
) {
205 Type designerType
= GetTypeFromName (component
, dat
.DesignerTypeName
);
206 if (designerType
!= null)
207 return (IDesigner
) Activator
.CreateInstance (designerType
);
214 [ReflectionPermission (SecurityAction
.LinkDemand
, TypeInformation
= true, MemberAccess
= true)]
215 public static EventDescriptor
CreateEvent (Type componentType
,
218 params Attribute
[] attributes
)
220 return new ReflectionEventDescriptor (componentType
, name
, type
, attributes
);
223 [ReflectionPermission (SecurityAction
.LinkDemand
, TypeInformation
= true, MemberAccess
= true)]
224 public static EventDescriptor
CreateEvent (Type componentType
,
225 EventDescriptor oldEventDescriptor
,
226 params Attribute
[] attributes
)
228 return new ReflectionEventDescriptor (componentType
, oldEventDescriptor
, attributes
);
231 [ReflectionPermission (SecurityAction
.LinkDemand
, TypeInformation
= true, MemberAccess
= true)]
232 public static PropertyDescriptor
CreateProperty (Type componentType
,
235 params Attribute
[] attributes
)
237 return new ReflectionPropertyDescriptor (componentType
, name
, type
, attributes
);
240 [ReflectionPermission (SecurityAction
.LinkDemand
, TypeInformation
= true, MemberAccess
= true)]
241 public static PropertyDescriptor
CreateProperty (Type componentType
,
242 PropertyDescriptor oldPropertyDescriptor
,
243 params Attribute
[] attributes
)
245 return new ReflectionPropertyDescriptor (componentType
, oldPropertyDescriptor
, attributes
);
248 public static AttributeCollection
GetAttributes (Type componentType
)
250 if (componentType
== null)
251 return AttributeCollection
.Empty
;
253 return GetTypeInfo (componentType
).GetAttributes ();
256 public static AttributeCollection
GetAttributes (object component
)
258 return GetAttributes (component
, false);
262 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
264 public static AttributeCollection
GetAttributes (object component
, bool noCustomTypeDesc
)
266 if (component
== null)
267 return AttributeCollection
.Empty
;
269 if (noCustomTypeDesc
== false && component
is ICustomTypeDescriptor
) {
270 return ((ICustomTypeDescriptor
) component
).GetAttributes ();
272 IComponent com
= component
as IComponent
;
273 if (com
!= null && com
.Site
!= null)
274 return GetComponentInfo (com
).GetAttributes ();
276 return GetTypeInfo (component
.GetType()).GetAttributes ();
280 public static string GetClassName (object component
)
282 return GetClassName (component
, false);
286 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
288 public static string GetClassName (object component
, bool noCustomTypeDesc
)
290 if (component
== null)
291 throw new ArgumentNullException ("component", "component cannot be null");
293 if (noCustomTypeDesc
== false && component
is ICustomTypeDescriptor
) {
294 String res
= ((ICustomTypeDescriptor
) component
).GetClassName ();
296 res
= ((ICustomTypeDescriptor
) component
).GetComponentName ();
298 res
= component
.GetType ().FullName
;
301 return component
.GetType ().FullName
;
305 public static string GetComponentName (object component
)
307 return GetComponentName (component
, false);
311 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
313 public static string GetComponentName (object component
, bool noCustomTypeDesc
)
315 if (component
== null)
316 throw new ArgumentNullException ("component", "component cannot be null");
318 if (noCustomTypeDesc
== false && component
is ICustomTypeDescriptor
) {
319 return ((ICustomTypeDescriptor
) component
).GetComponentName ();
321 IComponent c
= component
as IComponent
;
322 if (c
!= null && c
.Site
!= null)
327 return component
.GetType().Name
;
333 [MonoNotSupported("")]
334 public static string GetFullComponentName (object component
)
336 throw new NotImplementedException ();
339 [MonoNotSupported("")]
340 public static string GetClassName (Type componentType
)
342 throw new NotImplementedException ();
346 public static TypeConverter
GetConverter (object component
)
348 return GetConverter (component
, false);
352 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
354 public static TypeConverter
GetConverter (object component
, bool noCustomTypeDesc
)
356 if (component
== null)
357 throw new ArgumentNullException ("component", "component cannot be null");
359 if (noCustomTypeDesc
== false && component
is ICustomTypeDescriptor
) {
360 return ((ICustomTypeDescriptor
) component
).GetConverter ();
363 Type converterType
= null;
364 AttributeCollection atts
= GetAttributes (component
, false);
365 TypeConverterAttribute tca
= (TypeConverterAttribute
) atts
[typeof(TypeConverterAttribute
)];
366 if (tca
!= null && tca
.ConverterTypeName
.Length
> 0)
367 converterType
= GetTypeFromName (component
as IComponent
, tca
.ConverterTypeName
);
368 if (converterType
== null)
369 converterType
= FindDefaultConverterType (component
.GetType ());
371 if (converterType
!= null) {
372 ConstructorInfo ci
= converterType
.GetConstructor (new Type
[] { typeof(Type) }
);
374 return (TypeConverter
) ci
.Invoke (new object[] { component.GetType () }
);
376 return (TypeConverter
) Activator
.CreateInstance (converterType
);
382 private static ArrayList DefaultConverters
385 lock (creatingDefaultConverters
) {
386 if (defaultConverters
!= null)
387 return defaultConverters
;
389 defaultConverters
= new ArrayList ();
390 defaultConverters
.Add (new DictionaryEntry (typeof (bool), typeof (BooleanConverter
)));
391 defaultConverters
.Add (new DictionaryEntry (typeof (byte), typeof (ByteConverter
)));
392 defaultConverters
.Add (new DictionaryEntry (typeof (sbyte), typeof (SByteConverter
)));
393 defaultConverters
.Add (new DictionaryEntry (typeof (string), typeof (StringConverter
)));
394 defaultConverters
.Add (new DictionaryEntry (typeof (char), typeof (CharConverter
)));
395 defaultConverters
.Add (new DictionaryEntry (typeof (short), typeof (Int16Converter
)));
396 defaultConverters
.Add (new DictionaryEntry (typeof (int), typeof (Int32Converter
)));
397 defaultConverters
.Add (new DictionaryEntry (typeof (long), typeof (Int64Converter
)));
398 defaultConverters
.Add (new DictionaryEntry (typeof (ushort), typeof (UInt16Converter
)));
399 defaultConverters
.Add (new DictionaryEntry (typeof (uint), typeof (UInt32Converter
)));
400 defaultConverters
.Add (new DictionaryEntry (typeof (ulong), typeof (UInt64Converter
)));
401 defaultConverters
.Add (new DictionaryEntry (typeof (float), typeof (SingleConverter
)));
402 defaultConverters
.Add (new DictionaryEntry (typeof (double), typeof (DoubleConverter
)));
403 defaultConverters
.Add (new DictionaryEntry (typeof (decimal), typeof (DecimalConverter
)));
404 defaultConverters
.Add (new DictionaryEntry (typeof (void), typeof (TypeConverter
)));
405 defaultConverters
.Add (new DictionaryEntry (typeof (Array
), typeof (ArrayConverter
)));
406 defaultConverters
.Add (new DictionaryEntry (typeof (CultureInfo
), typeof (CultureInfoConverter
)));
407 defaultConverters
.Add (new DictionaryEntry (typeof (DateTime
), typeof (DateTimeConverter
)));
408 defaultConverters
.Add (new DictionaryEntry (typeof (Guid
), typeof (GuidConverter
)));
409 defaultConverters
.Add (new DictionaryEntry (typeof (TimeSpan
), typeof (TimeSpanConverter
)));
410 defaultConverters
.Add (new DictionaryEntry (typeof (ICollection
), typeof (CollectionConverter
)));
411 defaultConverters
.Add (new DictionaryEntry (typeof (Enum
), typeof (EnumConverter
)));
413 return defaultConverters
;
417 public static TypeConverter
GetConverter (Type type
)
420 throw new ArgumentNullException ("type");
422 Type converterType
= null;
423 AttributeCollection atts
= GetAttributes (type
);
424 TypeConverterAttribute tca
= (TypeConverterAttribute
) atts
[typeof(TypeConverterAttribute
)];
425 if (tca
!= null && tca
.ConverterTypeName
.Length
> 0)
426 converterType
= GetTypeFromName (null, tca
.ConverterTypeName
);
427 if (converterType
== null)
428 converterType
= FindDefaultConverterType (type
);
430 if (converterType
!= null) {
431 ConstructorInfo ci
= converterType
.GetConstructor (new Type
[] { typeof(Type) }
);
433 return (TypeConverter
) ci
.Invoke (new object[] { type }
);
435 return (TypeConverter
) Activator
.CreateInstance (converterType
);
441 private static Type
FindDefaultConverterType (Type type
)
443 Type converterType
= null;
446 if (type
.IsGenericType
&& type
.GetGenericTypeDefinition() == typeof(Nullable
<>))
447 return typeof(NullableConverter
);
449 // Is there a default converter
450 foreach (DictionaryEntry entry
in DefaultConverters
) {
451 if ((Type
)entry
.Key
== type
)
452 return (Type
)entry
.Value
;
456 // Find default converter with a baseType this baseType is assignable to
457 Type baseType
= type
;
458 while (baseType
!= null && baseType
!= typeof (object)) {
459 foreach (DictionaryEntry entry
in DefaultConverters
) {
460 Type defType
= (Type
)entry
.Key
;
461 if (defType
.IsAssignableFrom (baseType
)) {
462 converterType
= (Type
)entry
.Value
;
466 baseType
= baseType
.BaseType
;
469 if (converterType
== null) {
470 if (type
!= null && type
.IsInterface
)
471 converterType
= typeof (ReferenceConverter
);
473 converterType
= typeof (TypeConverter
);
476 return converterType
;
479 public static EventDescriptor
GetDefaultEvent (Type componentType
)
481 return GetTypeInfo (componentType
).GetDefaultEvent ();
484 public static EventDescriptor
GetDefaultEvent (object component
)
486 return GetDefaultEvent (component
, false);
490 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
492 public static EventDescriptor
GetDefaultEvent (object component
, bool noCustomTypeDesc
)
494 if (!noCustomTypeDesc
&& (component
is ICustomTypeDescriptor
))
495 return ((ICustomTypeDescriptor
) component
).GetDefaultEvent ();
497 IComponent com
= component
as IComponent
;
498 if (com
!= null && com
.Site
!= null)
499 return GetComponentInfo (com
).GetDefaultEvent ();
501 return GetTypeInfo (component
.GetType()).GetDefaultEvent ();
505 public static PropertyDescriptor
GetDefaultProperty (Type componentType
)
507 return GetTypeInfo (componentType
).GetDefaultProperty ();
510 public static PropertyDescriptor
GetDefaultProperty (object component
)
512 return GetDefaultProperty (component
, false);
516 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
518 public static PropertyDescriptor
GetDefaultProperty (object component
, bool noCustomTypeDesc
)
520 if (!noCustomTypeDesc
&& (component
is ICustomTypeDescriptor
))
521 return ((ICustomTypeDescriptor
) component
).GetDefaultProperty ();
523 IComponent com
= component
as IComponent
;
524 if (com
!= null && com
.Site
!= null)
525 return GetComponentInfo (com
).GetDefaultProperty ();
527 return GetTypeInfo (component
.GetType()).GetDefaultProperty ();
531 internal static object CreateEditor (Type t
, Type componentType
)
537 return Activator
.CreateInstance (t
);
541 return Activator
.CreateInstance (t
, new object [] {componentType}
);
547 private static object FindEditorInTable (Type componentType
, Type editorBaseType
, Hashtable table
)
549 object editorReference
= null;
550 object editor
= null;
552 if (componentType
== null || editorBaseType
== null || table
== null)
555 Type ct
= componentType
;
557 editorReference
= table
[ct
];
558 if (editorReference
!= null)
563 if (editorReference
== null) {
564 foreach (Type iface
in componentType
.GetInterfaces ()) {
565 editorReference
= table
[iface
];
566 if (editorReference
!= null)
571 if (editorReference
== null)
574 if (editorReference
is string)
575 editor
= CreateEditor (Type
.GetType ((string) editorReference
), componentType
);
576 else if (editorReference
is Type
)
577 editor
= CreateEditor ((Type
) editorReference
, componentType
);
578 else if (editorReference
.GetType ().IsSubclassOf (editorBaseType
))
579 editor
= editorReference
;
582 table
[componentType
] = editor
;
587 public static object GetEditor (Type componentType
, Type editorBaseType
)
589 Type editorType
= null;
590 object editor
= null;
591 object [] atts
= componentType
.GetCustomAttributes (typeof(EditorAttribute
), true);
593 if (atts
!= null && atts
.Length
!= 0) {
594 foreach (EditorAttribute ea
in atts
) {
595 editorType
= GetTypeFromName (null, ea
.EditorTypeName
);
596 if (editorType
!= null && editorType
.IsSubclassOf(editorBaseType
))
601 if (editorType
!= null)
602 editor
= CreateEditor (editorType
, componentType
);
604 if (editorType
== null || editor
== null) {
606 // Make sure the editorBaseType's static constructor has been called,
607 // since that's where we're putting the initialization of its editor table.
609 System
.Runtime
.CompilerServices
.RuntimeHelpers
.RunClassConstructor (editorBaseType
.TypeHandle
);
612 editor
= FindEditorInTable (componentType
, editorBaseType
, editors
[editorBaseType
] as Hashtable
);
618 public static object GetEditor (object component
, Type editorBaseType
)
620 return GetEditor (component
, editorBaseType
, false);
624 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
626 public static object GetEditor (object component
, Type editorBaseType
, bool noCustomTypeDesc
)
628 if (component
== null)
629 throw new ArgumentNullException ("component");
630 if (editorBaseType
== null)
631 throw new ArgumentNullException ("editorBaseType");
633 if (!noCustomTypeDesc
&& (component
is ICustomTypeDescriptor
))
634 return ((ICustomTypeDescriptor
) component
).GetEditor (editorBaseType
);
636 object [] atts
= component
.GetType ().GetCustomAttributes (typeof (EditorAttribute
), true);
637 if (atts
.Length
== 0)
639 string target
= editorBaseType
.AssemblyQualifiedName
;
641 foreach (EditorAttribute ea
in atts
){
642 if (ea
.EditorBaseTypeName
== target
){
643 Type t
= Type
.GetType (ea
.EditorTypeName
, true);
645 return Activator
.CreateInstance (t
);
651 public static EventDescriptorCollection
GetEvents (object component
)
653 return GetEvents (component
, false);
656 public static EventDescriptorCollection
GetEvents (Type componentType
)
658 return GetEvents (componentType
, null);
661 public static EventDescriptorCollection
GetEvents (object component
, Attribute
[] attributes
)
663 return GetEvents (component
, attributes
, false);
667 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
669 public static EventDescriptorCollection
GetEvents (object component
, bool noCustomTypeDesc
)
671 if (!noCustomTypeDesc
&& (component
is ICustomTypeDescriptor
))
672 return ((ICustomTypeDescriptor
) component
).GetEvents ();
674 IComponent com
= component
as IComponent
;
675 if (com
!= null && com
.Site
!= null)
676 return GetComponentInfo (com
).GetEvents ();
678 return GetTypeInfo (component
.GetType()).GetEvents ();
682 public static EventDescriptorCollection
GetEvents (Type componentType
, Attribute
[] attributes
)
684 return GetTypeInfo (componentType
).GetEvents (attributes
);
688 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
690 public static EventDescriptorCollection
GetEvents (object component
, Attribute
[] attributes
, bool noCustomTypeDesc
)
692 if (!noCustomTypeDesc
&& (component
is ICustomTypeDescriptor
))
693 return ((ICustomTypeDescriptor
) component
).GetEvents (attributes
);
695 IComponent com
= component
as IComponent
;
696 if (com
!= null && com
.Site
!= null)
697 return GetComponentInfo (com
).GetEvents (attributes
);
699 return GetTypeInfo (component
.GetType()).GetEvents (attributes
);
703 public static PropertyDescriptorCollection
GetProperties (object component
)
705 return GetProperties (component
, false);
708 public static PropertyDescriptorCollection
GetProperties (Type componentType
)
710 return GetProperties (componentType
, null);
713 public static PropertyDescriptorCollection
GetProperties (object component
, Attribute
[] attributes
)
715 return GetProperties (component
, attributes
, false);
718 public static PropertyDescriptorCollection
GetProperties (object component
, Attribute
[] attributes
, bool noCustomTypeDesc
)
720 if (component
== null)
721 return PropertyDescriptorCollection
.Empty
;
723 if (!noCustomTypeDesc
&& (component
is ICustomTypeDescriptor
))
724 return ((ICustomTypeDescriptor
) component
).GetProperties (attributes
);
726 IComponent com
= component
as IComponent
;
727 if (com
!= null && com
.Site
!= null)
728 return GetComponentInfo (com
).GetProperties (attributes
);
730 return GetTypeInfo (component
.GetType()).GetProperties (attributes
);
735 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
737 public static PropertyDescriptorCollection
GetProperties (object component
, bool noCustomTypeDesc
)
739 if (component
== null)
740 return PropertyDescriptorCollection
.Empty
;
742 if (!noCustomTypeDesc
&& (component
is ICustomTypeDescriptor
))
743 return ((ICustomTypeDescriptor
) component
).GetProperties ();
745 IComponent com
= component
as IComponent
;
746 if (com
!= null && com
.Site
!= null)
747 return GetComponentInfo (com
).GetProperties ();
749 return GetTypeInfo (component
.GetType()).GetProperties ();
753 public static PropertyDescriptorCollection
GetProperties (Type componentType
, Attribute
[] attributes
)
755 return GetTypeInfo (componentType
).GetProperties (attributes
);
759 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
760 public static TypeDescriptionProvider
GetProvider (object instance
)
762 if (instance
== null)
763 throw new ArgumentNullException ("instance");
765 TypeDescriptionProvider ret
= null;
766 lock (componentDescriptionProvidersLock
) {
767 LinkedList
<TypeDescriptionProvider
> plist
;
768 WeakObjectWrapper instanceWrapper
= new WeakObjectWrapper (instance
);
770 if (componentDescriptionProviders
.TryGetValue (instanceWrapper
, out plist
) && plist
.Count
> 0)
771 ret
= plist
.Last
.Value
;
773 instanceWrapper
= null;
777 ret
= GetProvider (instance
.GetType ());
780 return new DefaultTypeDescriptionProvider ();
782 return new WrappedTypeDescriptionProvider (ret
);
785 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
786 public static TypeDescriptionProvider
GetProvider (Type type
)
789 throw new ArgumentNullException ("type");
791 TypeDescriptionProvider ret
= null;
792 lock (typeDescriptionProvidersLock
) {
793 LinkedList
<TypeDescriptionProvider
> plist
;
795 while (!typeDescriptionProviders
.TryGetValue (type
, out plist
)) {
797 type
= type
.BaseType
;
802 if (plist
!= null && plist
.Count
> 0)
803 ret
= plist
.Last
.Value
;
807 return new DefaultTypeDescriptionProvider ();
809 return new WrappedTypeDescriptionProvider (ret
);
812 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
813 public static Type
GetReflectionType (object instance
)
815 if (instance
== null)
816 throw new ArgumentNullException ("instance");
818 return instance
.GetType ();
821 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
822 public static Type
GetReflectionType (Type type
)
825 throw new ArgumentNullException ("type");
830 [MonoNotSupported("Associations not supported")]
831 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
832 public static void CreateAssociation (object primary
, object secondary
)
834 throw new NotImplementedException ();
837 [MonoNotSupported ("Associations not supported")]
838 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
839 public static object GetAssociation (Type type
, object primary
)
841 throw new NotImplementedException ();
844 [MonoNotSupported ("Associations not supported")]
845 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
846 public static void RemoveAssociation (object primary
, object secondary
)
848 throw new NotImplementedException ();
851 [MonoNotSupported ("Associations not supported")]
852 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
853 public static void RemoveAssociations (object primary
)
855 throw new NotImplementedException ();
858 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
859 public static void RemoveProvider (TypeDescriptionProvider provider
, object instance
)
861 if (provider
== null)
862 throw new ArgumentNullException ("provider");
863 if (instance
== null)
864 throw new ArgumentNullException ("instance");
866 //bool removed = false;
867 lock (componentDescriptionProvidersLock
) {
868 LinkedList
<TypeDescriptionProvider
> plist
;
869 WeakObjectWrapper instanceWrapper
= new WeakObjectWrapper (instance
);
871 if (componentDescriptionProviders
.TryGetValue (instanceWrapper
, out plist
) && plist
.Count
> 0) {
872 RemoveProvider (provider
, plist
);
876 instanceWrapper
= null;
879 var refreshed
= Refreshed
;
880 if (refreshed
!= null)
881 refreshed (new RefreshEventArgs (instance
));
884 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
885 public static void RemoveProvider (TypeDescriptionProvider provider
, Type type
)
887 if (provider
== null)
888 throw new ArgumentNullException ("provider");
890 throw new ArgumentNullException ("type");
892 lock (typeDescriptionProvidersLock
) {
893 LinkedList
<TypeDescriptionProvider
> plist
;
895 if (typeDescriptionProviders
.TryGetValue (type
, out plist
) && plist
.Count
> 0) {
896 RemoveProvider (provider
, plist
);
900 var refreshed
= Refreshed
;
901 if (refreshed
!= null)
902 refreshed (new RefreshEventArgs (type
));
905 static void RemoveProvider (TypeDescriptionProvider provider
, LinkedList
<TypeDescriptionProvider
> plist
)
907 LinkedListNode
<TypeDescriptionProvider
> node
= plist
.Last
;
908 LinkedListNode
<TypeDescriptionProvider
> first
= plist
.First
;
909 TypeDescriptionProvider p
;
920 node
= node
.Previous
;
926 public static void SortDescriptorArray (IList infos
)
928 string[] names
= new string [infos
.Count
];
929 object[] values
= new object [infos
.Count
];
930 for (int n
=0; n
<names
.Length
; n
++) {
931 names
[n
] = ((MemberDescriptor
)infos
[n
]).Name
;
932 values
[n
] = infos
[n
];
934 Array
.Sort (names
, values
);
936 foreach (object ob
in values
)
941 // well, ComObjectType is not implemented, but we don't support COM anyways ...
942 [Obsolete ("Use ComObjectType")]
944 public static IComNativeDescriptorHandler ComNativeDescriptorHandler
{
945 [PermissionSet (SecurityAction
.LinkDemand
, Unrestricted
= true)]
946 get { return descriptorHandler; }
947 [PermissionSet (SecurityAction
.LinkDemand
, Unrestricted
= true)]
948 set { descriptorHandler = value; }
951 public static void Refresh (Assembly assembly
)
953 foreach (Type type
in assembly
.GetTypes())
957 public static void Refresh (Module module
)
959 foreach (Type type
in module
.GetTypes())
963 public static void Refresh (object component
)
965 lock (componentTable
)
967 componentTable
.Remove (component
);
969 if (Refreshed
!= null) Refreshed (new RefreshEventArgs (component
));
972 public static void Refresh (Type type
)
976 typeTable
.Remove (type
);
978 if (Refreshed
!= null) Refreshed (new RefreshEventArgs (type
));
981 static EventHandler onDispose
;
983 static void OnComponentDisposed (object sender
, EventArgs args
)
985 lock (componentTable
) {
986 componentTable
.Remove (sender
);
990 public static event RefreshEventHandler Refreshed
;
992 internal static ComponentInfo
GetComponentInfo (IComponent com
)
994 lock (componentTable
)
996 ComponentInfo ci
= (ComponentInfo
) componentTable
[com
];
998 if (onDispose
== null)
999 onDispose
= new EventHandler (OnComponentDisposed
);
1001 com
.Disposed
+= onDispose
;
1002 ci
= new ComponentInfo (com
);
1003 componentTable
[com
] = ci
;
1009 internal static TypeInfo
GetTypeInfo (Type type
)
1013 TypeInfo ci
= (TypeInfo
) typeTable
[type
];
1015 ci
= new TypeInfo (type
);
1016 typeTable
[type
] = ci
;
1022 private static Type
GetTypeFromName (IComponent component
, string typeName
)
1025 if (component
!= null && component
.Site
!= null) {
1026 ITypeResolutionService resver
= (ITypeResolutionService
) component
.Site
.GetService (typeof(ITypeResolutionService
));
1028 type
= resver
.GetType (typeName
);
1031 type
= Type
.GetType (typeName
);
1036 sealed class AttributeProvider
: TypeDescriptionProvider
1038 Attribute
[] attributes
;
1040 public AttributeProvider (Attribute
[] attributes
, TypeDescriptionProvider parent
)
1043 this.attributes
= attributes
;
1046 public override ICustomTypeDescriptor
GetTypeDescriptor (Type type
, object instance
)
1048 return new AttributeTypeDescriptor (base.GetTypeDescriptor (type
, instance
), attributes
);
1051 sealed class AttributeTypeDescriptor
: CustomTypeDescriptor
1053 Attribute
[] attributes
;
1055 public AttributeTypeDescriptor (ICustomTypeDescriptor parent
, Attribute
[] attributes
)
1058 this.attributes
= attributes
;
1061 public override AttributeCollection
GetAttributes ()
1063 AttributeCollection attrs
= base.GetAttributes ();
1065 if (attrs
!= null && attrs
.Count
> 0)
1066 return AttributeCollection
.FromExisting (attrs
, attributes
);
1068 return new AttributeCollection (attributes
);
1073 sealed class WrappedTypeDescriptionProvider
: TypeDescriptionProvider
1075 public TypeDescriptionProvider Wrapped { get; private set; }
1077 public WrappedTypeDescriptionProvider (TypeDescriptionProvider wrapped
)
1082 public override object CreateInstance (IServiceProvider provider
, Type objectType
, Type
[] argTypes
, object[] args
)
1084 TypeDescriptionProvider wrapped
= Wrapped
;
1086 if (wrapped
== null)
1087 return base.CreateInstance (provider
, objectType
, argTypes
, args
);
1089 return wrapped
.CreateInstance (provider
, objectType
, argTypes
, args
);
1092 public override IDictionary
GetCache (object instance
)
1094 TypeDescriptionProvider wrapped
= Wrapped
;
1096 if (wrapped
== null)
1097 return base.GetCache (instance
);
1099 return wrapped
.GetCache (instance
);
1102 public override ICustomTypeDescriptor
GetExtendedTypeDescriptor (object instance
)
1104 return new DefaultTypeDescriptor (this, null, instance
);
1107 public override string GetFullComponentName (object component
)
1109 TypeDescriptionProvider wrapped
= Wrapped
;
1111 if (wrapped
== null)
1112 return base.GetFullComponentName (component
);
1114 return wrapped
.GetFullComponentName (component
);
1117 public override Type
GetReflectionType (Type type
, object instance
)
1119 TypeDescriptionProvider wrapped
= Wrapped
;
1121 if (wrapped
== null)
1122 return base.GetReflectionType (type
, instance
);
1124 return wrapped
.GetReflectionType (type
, instance
);
1127 public override ICustomTypeDescriptor
GetTypeDescriptor (Type objectType
, object instance
)
1129 TypeDescriptionProvider wrapped
= Wrapped
;
1131 if (wrapped
== null)
1132 return new DefaultTypeDescriptor (this, objectType
, instance
);
1134 return wrapped
.GetTypeDescriptor (objectType
, instance
);
1138 // TODO: this needs more work
1139 sealed class DefaultTypeDescriptor
: CustomTypeDescriptor
1141 TypeDescriptionProvider owner
;
1145 public DefaultTypeDescriptor (TypeDescriptionProvider owner
, Type objectType
, object instance
)
1148 this.objectType
= objectType
;
1149 this.instance
= instance
;
1152 public override AttributeCollection
GetAttributes ()
1154 var wrapped
= owner
as WrappedTypeDescriptionProvider
;
1156 if (wrapped
!= null)
1157 return wrapped
.Wrapped
.GetTypeDescriptor (objectType
, instance
).GetAttributes ();
1159 if (instance
!= null)
1160 return TypeDescriptor
.GetAttributes (instance
, false);
1162 if (objectType
!= null)
1163 return TypeDescriptor
.GetTypeInfo (objectType
).GetAttributes ();
1165 return base.GetAttributes ();
1168 public override string GetClassName ()
1170 var wrapped
= owner
as WrappedTypeDescriptionProvider
;
1172 if (wrapped
!= null)
1173 return wrapped
.Wrapped
.GetTypeDescriptor (objectType
, instance
).GetClassName ();
1175 return base.GetClassName ();
1178 public override PropertyDescriptor
GetDefaultProperty ()
1180 var wrapped
= owner
as WrappedTypeDescriptionProvider
;
1182 if (wrapped
!= null)
1183 return wrapped
.Wrapped
.GetTypeDescriptor (objectType
, instance
).GetDefaultProperty ();
1185 PropertyDescriptor ret
;
1186 if (objectType
!= null)
1187 ret
= TypeDescriptor
.GetTypeInfo (objectType
).GetDefaultProperty ();
1188 else if (instance
!= null)
1189 ret
= TypeDescriptor
.GetTypeInfo (instance
.GetType ()).GetDefaultProperty ();
1191 ret
= base.GetDefaultProperty ();
1196 public override PropertyDescriptorCollection
GetProperties ()
1198 var wrapped
= owner
as WrappedTypeDescriptionProvider
;
1200 if (wrapped
!= null)
1201 return wrapped
.Wrapped
.GetTypeDescriptor (objectType
, instance
).GetProperties ();
1203 if (instance
!= null)
1204 return TypeDescriptor
.GetProperties (instance
, null, false);
1206 if (objectType
!= null)
1207 return TypeDescriptor
.GetTypeInfo (objectType
).GetProperties (null);
1209 return base.GetProperties ();
1213 sealed class DefaultTypeDescriptionProvider
: TypeDescriptionProvider
1215 public DefaultTypeDescriptionProvider ()
1219 public override ICustomTypeDescriptor
GetExtendedTypeDescriptor (object instance
)
1221 return new DefaultTypeDescriptor (this, null, instance
);
1224 public override ICustomTypeDescriptor
GetTypeDescriptor (Type objectType
, object instance
)
1226 return new DefaultTypeDescriptor (this, objectType
, instance
);
1232 internal abstract class Info
1235 EventDescriptor _defaultEvent
;
1236 bool _gotDefaultEvent
;
1237 PropertyDescriptor _defaultProperty
;
1238 bool _gotDefaultProperty
;
1239 AttributeCollection _attributes
;
1241 public Info (Type infoType
)
1243 _infoType
= infoType
;
1246 public abstract AttributeCollection
GetAttributes ();
1247 public abstract EventDescriptorCollection
GetEvents ();
1248 public abstract PropertyDescriptorCollection
GetProperties ();
1250 public Type InfoType
1252 get { return _infoType; }
1255 public EventDescriptorCollection
GetEvents (Attribute
[] attributes
)
1257 EventDescriptorCollection evs
= GetEvents ();
1258 if (attributes
== null)
1261 return evs
.Filter (attributes
);
1264 public PropertyDescriptorCollection
GetProperties (Attribute
[] attributes
)
1266 PropertyDescriptorCollection props
= GetProperties ();
1267 if (attributes
== null)
1270 return props
.Filter (attributes
);
1273 public EventDescriptor
GetDefaultEvent ()
1275 if (_gotDefaultEvent
)
1276 return _defaultEvent
;
1278 DefaultEventAttribute attr
= (DefaultEventAttribute
) GetAttributes()[typeof(DefaultEventAttribute
)];
1279 if (attr
== null || attr
.Name
== null)
1280 _defaultEvent
= null;
1282 EventDescriptorCollection events
= GetEvents ();
1283 _defaultEvent
= events
[attr
.Name
];
1285 // In our test case (TypeDescriptorTest.TestGetDefaultEvent), we have
1286 // a scenario where a custom filter adds the DefaultEventAttribute,
1287 // but its FilterEvents method removes the event the
1288 // DefaultEventAttribute applied to. .NET 1.x accepts this and returns
1289 // the *other* event defined in the class.
1291 // Consequently, we know we have a DefaultEvent, but we need to check
1292 // and ensure that the requested event is unfiltered. If it is, just
1293 // grab the first element in the collection.
1294 if (_defaultEvent
== null && events
.Count
> 0)
1295 _defaultEvent
= events
[0];
1298 _gotDefaultEvent
= true;
1299 return _defaultEvent
;
1302 public PropertyDescriptor
GetDefaultProperty ()
1304 if (_gotDefaultProperty
)
1305 return _defaultProperty
;
1307 DefaultPropertyAttribute attr
= (DefaultPropertyAttribute
) GetAttributes()[typeof(DefaultPropertyAttribute
)];
1308 if (attr
== null || attr
.Name
== null)
1309 _defaultProperty
= null;
1311 PropertyDescriptorCollection properties
= GetProperties ();
1312 _defaultProperty
= properties
[attr
.Name
];
1314 _gotDefaultProperty
= true;
1315 return _defaultProperty
;
1318 protected AttributeCollection
GetAttributes (IComponent comp
)
1320 if (_attributes
!= null)
1324 ArrayList attributesList
= new ArrayList ();
1326 // 1) Attributes of the type
1327 foreach (Attribute attribute
in _infoType
.GetCustomAttributes (false))
1328 attributesList
.Add (attribute
);
1330 // 2) Attributes of the base types
1331 Type baseType
= _infoType
.BaseType
;
1332 while (baseType
!= null && baseType
!= typeof (object)) {
1333 foreach (Attribute attribute
in baseType
.GetCustomAttributes (false))
1334 attributesList
.Add (attribute
);
1335 baseType
= baseType
.BaseType
;
1338 // 3) Attributes of the type's implemented interfaces and their interfaces as well
1339 foreach (Type inface
in _infoType
.GetInterfaces ())
1340 foreach (Attribute attribute
in TypeDescriptor
.GetAttributes (inface
))
1341 attributesList
.Add (attribute
);
1343 // Filter out duplicate attributes, so that the base types have higher precedence
1344 // than the interfaces and the type higher than both.
1345 Hashtable attributesTable
= new Hashtable ();
1346 for (int i
= attributesList
.Count
- 1; i
>= 0; i
--) {
1347 Attribute attribute
= (Attribute
)attributesList
[i
];
1348 attributesTable
[attribute
.TypeId
] = attribute
;
1351 if (comp
!= null && comp
.Site
!= null)
1353 ITypeDescriptorFilterService filter
= (ITypeDescriptorFilterService
) comp
.Site
.GetService (typeof(ITypeDescriptorFilterService
));
1355 cache
= filter
.FilterAttributes (comp
, attributesTable
);
1358 Attribute
[] attributes
= new Attribute
[attributesTable
.Values
.Count
];
1359 attributesTable
.Values
.CopyTo (attributes
, 0);
1360 AttributeCollection attCol
= new AttributeCollection (attributes
);
1362 _attributes
= attCol
;
1367 internal class ComponentInfo
: Info
1369 IComponent _component
;
1370 EventDescriptorCollection _events
;
1371 PropertyDescriptorCollection _properties
;
1373 public ComponentInfo (IComponent component
): base (component
.GetType())
1375 _component
= component
;
1378 public override AttributeCollection
GetAttributes ()
1380 return base.GetAttributes (_component
);
1383 public override EventDescriptorCollection
GetEvents ()
1385 if (_events
!= null)
1389 EventInfo
[] events
= _component
.GetType().GetEvents ();
1390 Hashtable t
= new Hashtable ();
1391 foreach (EventInfo ev
in events
)
1392 t
[ev
.Name
] = new ReflectionEventDescriptor (ev
);
1394 if (_component
.Site
!= null)
1396 ITypeDescriptorFilterService filter
= (ITypeDescriptorFilterService
) _component
.Site
.GetService (typeof(ITypeDescriptorFilterService
));
1398 cache
= filter
.FilterEvents (_component
, t
);
1401 ArrayList atts
= new ArrayList ();
1402 atts
.AddRange (t
.Values
);
1403 EventDescriptorCollection attCol
= new EventDescriptorCollection (atts
);
1404 if (cache
) _events
= attCol
;
1408 public override PropertyDescriptorCollection
GetProperties ()
1410 if (_properties
!= null)
1414 PropertyInfo
[] props
= _component
.GetType().GetProperties (BindingFlags
.Instance
| BindingFlags
.Public
);
1415 Hashtable t
= new Hashtable ();
1416 for (int i
= props
.Length
-1; i
>= 0; i
--)
1417 t
[props
[i
].Name
] = new ReflectionPropertyDescriptor (props
[i
]);
1419 if (_component
.Site
!= null)
1421 ITypeDescriptorFilterService filter
= (ITypeDescriptorFilterService
) _component
.Site
.GetService (typeof(ITypeDescriptorFilterService
));
1423 cache
= filter
.FilterProperties (_component
, t
);
1426 PropertyDescriptor
[] descriptors
= new PropertyDescriptor
[t
.Values
.Count
];
1427 t
.Values
.CopyTo (descriptors
, 0);
1428 PropertyDescriptorCollection attCol
= new PropertyDescriptorCollection (descriptors
, true);
1430 _properties
= attCol
;
1435 internal class TypeInfo
: Info
1437 EventDescriptorCollection _events
;
1438 PropertyDescriptorCollection _properties
;
1440 public TypeInfo (Type t
): base (t
)
1444 public override AttributeCollection
GetAttributes ()
1446 return base.GetAttributes (null);
1449 public override EventDescriptorCollection
GetEvents ()
1451 if (_events
!= null)
1454 EventInfo
[] events
= InfoType
.GetEvents ();
1455 EventDescriptor
[] descs
= new EventDescriptor
[events
.Length
];
1456 for (int n
=0; n
<events
.Length
; n
++)
1457 descs
[n
] = new ReflectionEventDescriptor (events
[n
]);
1459 _events
= new EventDescriptorCollection (descs
);
1463 public override PropertyDescriptorCollection
GetProperties ()
1465 if (_properties
!= null)
1468 Hashtable propertiesHash
= new Hashtable (); // name - null
1469 ArrayList propertiesList
= new ArrayList (); // propertydescriptors
1470 Type currentType
= InfoType
;
1471 // Getting properties type by type, because in the case of a property in the child type, where
1472 // the "new" keyword is used and also the return type is changed Type.GetProperties returns
1473 // also the parent property.
1475 // Note that we also have to preserve the properties order here.
1477 while (currentType
!= null && currentType
!= typeof (object)) {
1478 PropertyInfo
[] props
= currentType
.GetProperties (BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.DeclaredOnly
);
1479 foreach (PropertyInfo property
in props
) {
1480 if (property
.GetIndexParameters ().Length
== 0 &&
1482 !propertiesHash
.ContainsKey (property
.Name
)) {
1483 propertiesList
.Add (new ReflectionPropertyDescriptor (property
));
1484 propertiesHash
.Add (property
.Name
, null);
1487 currentType
= currentType
.BaseType
;
1490 _properties
= new PropertyDescriptorCollection ((PropertyDescriptor
[]) propertiesList
.ToArray (typeof (PropertyDescriptor
)), true);