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;
42 using System.Collections.Generic;
44 namespace System.ComponentModel
47 public sealed class TypeDescriptor
49 private static readonly object creatingDefaultConverters = new object ();
50 private static ArrayList defaultConverters;
51 private static IComNativeDescriptorHandler descriptorHandler;
52 private static Hashtable componentTable = new Hashtable ();
53 private static Hashtable typeTable = new Hashtable ();
54 private static Hashtable editors;
56 static object typeDescriptionProvidersLock = new object ();
57 static Dictionary <Type, LinkedList <TypeDescriptionProvider>> typeDescriptionProviders;
59 static object componentDescriptionProvidersLock = new object ();
60 static Dictionary <WeakObjectWrapper, LinkedList <TypeDescriptionProvider>> componentDescriptionProviders;
62 static TypeDescriptor ()
64 typeDescriptionProviders = new Dictionary <Type, LinkedList <TypeDescriptionProvider>> ();
65 componentDescriptionProviders = new Dictionary <WeakObjectWrapper, LinkedList <TypeDescriptionProvider>> (new WeakObjectWrapperComparer ());
68 private TypeDescriptor ()
72 [MonoNotSupported ("Mono does not support COM")]
73 [EditorBrowsable (EditorBrowsableState.Advanced)]
74 public static Type ComObjectType {
75 get { throw new NotImplementedException (); }
79 [EditorBrowsable (EditorBrowsableState.Advanced)]
80 public static Type InterfaceType {
82 return typeof (TypeDescriptorInterface);
87 [EditorBrowsable (EditorBrowsableState.Advanced)]
88 public static TypeDescriptionProvider AddAttributes (object instance, params Attribute [] attributes)
91 throw new ArgumentNullException ("instance");
92 if (attributes == null)
93 throw new ArgumentNullException ("attributes");
95 var ret = new AttributeProvider (attributes, GetProvider (instance));
96 AddProvider (ret, instance);
101 [EditorBrowsable (EditorBrowsableState.Advanced)]
102 public static TypeDescriptionProvider AddAttributes (Type type, params Attribute [] attributes)
105 throw new ArgumentNullException ("type");
106 if (attributes == null)
107 throw new ArgumentNullException ("attributes");
109 var ret = new AttributeProvider (attributes, GetProvider (type));
110 AddProvider (ret, type);
115 [EditorBrowsable (EditorBrowsableState.Advanced)]
116 public static void AddProvider (TypeDescriptionProvider provider, object instance)
118 if (provider == null)
119 throw new ArgumentNullException ("provider");
120 if (instance == null)
121 throw new ArgumentNullException ("instance");
123 lock (componentDescriptionProvidersLock) {
124 LinkedList <TypeDescriptionProvider> plist;
125 WeakObjectWrapper instanceWrapper = new WeakObjectWrapper (instance);
127 if (!componentDescriptionProviders.TryGetValue (instanceWrapper, out plist)) {
128 plist = new LinkedList <TypeDescriptionProvider> ();
129 componentDescriptionProviders.Add (new WeakObjectWrapper (instance), plist);
132 plist.AddLast (provider);
133 instanceWrapper = null;
138 [EditorBrowsable (EditorBrowsableState.Advanced)]
139 public static void AddProvider (TypeDescriptionProvider provider, Type type)
141 if (provider == null)
142 throw new ArgumentNullException ("provider");
144 throw new ArgumentNullException ("type");
146 lock (typeDescriptionProvidersLock) {
147 LinkedList <TypeDescriptionProvider> plist;
149 if (!typeDescriptionProviders.TryGetValue (type, out plist)) {
150 plist = new LinkedList <TypeDescriptionProvider> ();
151 typeDescriptionProviders.Add (type, plist);
154 plist.AddLast (provider);
160 public static object CreateInstance (IServiceProvider provider, Type objectType, Type [] argTypes, object [] args)
162 if (objectType == null)
163 throw new ArgumentNullException ("objectType");
165 object instance = null;
167 if (provider != null) {
168 TypeDescriptionProvider typeDescrProvider = provider.GetService (typeof (TypeDescriptionProvider)) as TypeDescriptionProvider;
169 if (typeDescrProvider != null)
170 instance = typeDescrProvider.CreateInstance (provider, objectType, argTypes, args);
173 // TODO: also search and use the internal providers table once Add/RemoveProvider have been implemented
175 if (instance == null)
176 instance = Activator.CreateInstance (objectType, args);
181 [EditorBrowsable (EditorBrowsableState.Advanced)]
187 static void AddEditorTable (Type editorBaseType, Hashtable table)
189 if (editorBaseType == null)
190 throw new ArgumentNullException ("editorBaseType");
193 editors = new Hashtable ();
195 if (!editors.ContainsKey (editorBaseType))
196 editors [editorBaseType] = table;
199 public static IDesigner CreateDesigner(IComponent component, Type designerBaseType)
201 string tn = designerBaseType.AssemblyQualifiedName;
202 AttributeCollection col = GetAttributes (component);
204 foreach (Attribute at in col) {
205 DesignerAttribute dat = at as DesignerAttribute;
206 if (dat != null && tn == dat.DesignerBaseTypeName) {
207 Type designerType = GetTypeFromName (component, dat.DesignerTypeName);
208 if (designerType != null)
209 return (IDesigner) Activator.CreateInstance (designerType);
216 [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
217 public static EventDescriptor CreateEvent (Type componentType,
220 params Attribute [] attributes)
222 return new ReflectionEventDescriptor (componentType, name, type, attributes);
225 [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
226 public static EventDescriptor CreateEvent (Type componentType,
227 EventDescriptor oldEventDescriptor,
228 params Attribute [] attributes)
230 return new ReflectionEventDescriptor (componentType, oldEventDescriptor, attributes);
233 [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
234 public static PropertyDescriptor CreateProperty (Type componentType,
237 params Attribute [] attributes)
239 return new ReflectionPropertyDescriptor (componentType, name, type, attributes);
242 [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
243 public static PropertyDescriptor CreateProperty (Type componentType,
244 PropertyDescriptor oldPropertyDescriptor,
245 params Attribute [] attributes)
247 return new ReflectionPropertyDescriptor (componentType, oldPropertyDescriptor, attributes);
250 public static AttributeCollection GetAttributes (Type componentType)
252 if (componentType == null)
253 return AttributeCollection.Empty;
255 return GetTypeInfo (componentType).GetAttributes ();
258 public static AttributeCollection GetAttributes (object component)
260 return GetAttributes (component, false);
263 [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);
285 [EditorBrowsable (EditorBrowsableState.Advanced)]
286 public static string GetClassName (object component, bool noCustomTypeDesc)
288 if (component == null)
289 throw new ArgumentNullException ("component", "component cannot be null");
291 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
292 String res = ((ICustomTypeDescriptor) component).GetClassName ();
294 res = ((ICustomTypeDescriptor) component).GetComponentName ();
296 res = component.GetType ().FullName;
299 return component.GetType ().FullName;
303 public static string GetComponentName (object component)
305 return GetComponentName (component, false);
308 [EditorBrowsable (EditorBrowsableState.Advanced)]
309 public static string GetComponentName (object component, bool noCustomTypeDesc)
311 if (component == null)
312 throw new ArgumentNullException ("component", "component cannot be null");
314 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
315 return ((ICustomTypeDescriptor) component).GetComponentName ();
317 IComponent c = component as IComponent;
318 if (c != null && c.Site != null)
324 [MonoNotSupported("")]
325 public static string GetFullComponentName (object component)
327 throw new NotImplementedException ();
330 [MonoNotSupported("")]
331 public static string GetClassName (Type componentType)
333 throw new NotImplementedException ();
336 public static TypeConverter GetConverter (object component)
338 return GetConverter (component, false);
341 [EditorBrowsable (EditorBrowsableState.Advanced)]
342 public static TypeConverter GetConverter (object component, bool noCustomTypeDesc)
344 if (component == null)
345 throw new ArgumentNullException ("component", "component cannot be null");
347 if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
348 return ((ICustomTypeDescriptor) component).GetConverter ();
351 Type converterType = null;
352 AttributeCollection atts = GetAttributes (component, false);
353 TypeConverterAttribute tca = (TypeConverterAttribute) atts[typeof(TypeConverterAttribute)];
354 if (tca != null && tca.ConverterTypeName.Length > 0)
355 converterType = GetTypeFromName (component as IComponent, tca.ConverterTypeName);
356 if (converterType == null)
357 converterType = FindDefaultConverterType (component.GetType ());
359 if (converterType != null) {
360 ConstructorInfo ci = converterType.GetConstructor (new Type[] { typeof(Type) });
362 return (TypeConverter) ci.Invoke (new object[] { component.GetType () });
364 return (TypeConverter) Activator.CreateInstance (converterType);
370 private static ArrayList DefaultConverters
373 lock (creatingDefaultConverters) {
374 if (defaultConverters != null)
375 return defaultConverters;
377 defaultConverters = new ArrayList ();
378 defaultConverters.Add (new DictionaryEntry (typeof (bool), typeof (BooleanConverter)));
379 defaultConverters.Add (new DictionaryEntry (typeof (byte), typeof (ByteConverter)));
380 defaultConverters.Add (new DictionaryEntry (typeof (sbyte), typeof (SByteConverter)));
381 defaultConverters.Add (new DictionaryEntry (typeof (string), typeof (StringConverter)));
382 defaultConverters.Add (new DictionaryEntry (typeof (char), typeof (CharConverter)));
383 defaultConverters.Add (new DictionaryEntry (typeof (short), typeof (Int16Converter)));
384 defaultConverters.Add (new DictionaryEntry (typeof (int), typeof (Int32Converter)));
385 defaultConverters.Add (new DictionaryEntry (typeof (long), typeof (Int64Converter)));
386 defaultConverters.Add (new DictionaryEntry (typeof (ushort), typeof (UInt16Converter)));
387 defaultConverters.Add (new DictionaryEntry (typeof (uint), typeof (UInt32Converter)));
388 defaultConverters.Add (new DictionaryEntry (typeof (ulong), typeof (UInt64Converter)));
389 defaultConverters.Add (new DictionaryEntry (typeof (float), typeof (SingleConverter)));
390 defaultConverters.Add (new DictionaryEntry (typeof (double), typeof (DoubleConverter)));
391 defaultConverters.Add (new DictionaryEntry (typeof (decimal), typeof (DecimalConverter)));
392 defaultConverters.Add (new DictionaryEntry (typeof (void), typeof (TypeConverter)));
393 defaultConverters.Add (new DictionaryEntry (typeof (Array), typeof (ArrayConverter)));
394 defaultConverters.Add (new DictionaryEntry (typeof (CultureInfo), typeof (CultureInfoConverter)));
395 defaultConverters.Add (new DictionaryEntry (typeof (DateTime), typeof (DateTimeConverter)));
396 defaultConverters.Add (new DictionaryEntry (typeof (Guid), typeof (GuidConverter)));
397 defaultConverters.Add (new DictionaryEntry (typeof (TimeSpan), typeof (TimeSpanConverter)));
398 defaultConverters.Add (new DictionaryEntry (typeof (ICollection), typeof (CollectionConverter)));
399 defaultConverters.Add (new DictionaryEntry (typeof (Enum), typeof (EnumConverter)));
401 return defaultConverters;
405 public static TypeConverter GetConverter (Type type)
408 throw new ArgumentNullException ("type");
410 Type converterType = null;
411 AttributeCollection atts = GetAttributes (type);
412 TypeConverterAttribute tca = (TypeConverterAttribute) atts[typeof(TypeConverterAttribute)];
413 if (tca != null && tca.ConverterTypeName.Length > 0)
414 converterType = GetTypeFromName (null, tca.ConverterTypeName);
415 if (converterType == null)
416 converterType = FindDefaultConverterType (type);
418 if (converterType != null) {
419 ConstructorInfo ci = converterType.GetConstructor (new Type[] { typeof(Type) });
421 return (TypeConverter) ci.Invoke (new object[] { type });
423 return (TypeConverter) Activator.CreateInstance (converterType);
429 private static Type FindDefaultConverterType (Type type)
431 Type converterType = null;
433 if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
434 return typeof(NullableConverter);
435 // Is there a default converter
436 foreach (DictionaryEntry entry in DefaultConverters) {
437 if ((Type)entry.Key == type)
438 return (Type)entry.Value;
442 // Find default converter with a baseType this baseType is assignable to
443 Type baseType = type;
444 while (baseType != null && baseType != typeof (object)) {
445 foreach (DictionaryEntry entry in DefaultConverters) {
446 Type defType = (Type)entry.Key;
447 if (defType.IsAssignableFrom (baseType)) {
448 converterType = (Type)entry.Value;
452 baseType = baseType.BaseType;
455 if (converterType == null) {
456 if (type != null && type.IsInterface)
457 converterType = typeof (ReferenceConverter);
459 converterType = typeof (TypeConverter);
462 return converterType;
465 public static EventDescriptor GetDefaultEvent (Type componentType)
467 return GetTypeInfo (componentType).GetDefaultEvent ();
470 public static EventDescriptor GetDefaultEvent (object component)
472 return GetDefaultEvent (component, false);
475 [EditorBrowsable (EditorBrowsableState.Advanced)]
476 public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
478 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
479 return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
481 IComponent com = component as IComponent;
482 if (com != null && com.Site != null)
483 return GetComponentInfo (com).GetDefaultEvent ();
485 return GetTypeInfo (component.GetType()).GetDefaultEvent ();
489 public static PropertyDescriptor GetDefaultProperty (Type componentType)
491 return GetTypeInfo (componentType).GetDefaultProperty ();
494 public static PropertyDescriptor GetDefaultProperty (object component)
496 return GetDefaultProperty (component, false);
499 [EditorBrowsable (EditorBrowsableState.Advanced)]
500 public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
502 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
503 return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
505 IComponent com = component as IComponent;
506 if (com != null && com.Site != null)
507 return GetComponentInfo (com).GetDefaultProperty ();
509 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
513 internal static object CreateEditor (Type t, Type componentType)
519 return Activator.CreateInstance (t);
523 return Activator.CreateInstance (t, new object [] {componentType});
529 private static object FindEditorInTable (Type componentType, Type editorBaseType, Hashtable table)
531 object editorReference = null;
532 object editor = null;
534 if (componentType == null || editorBaseType == null || table == null)
537 Type ct = componentType;
539 editorReference = table [ct];
540 if (editorReference != null)
545 if (editorReference == null) {
546 foreach (Type iface in componentType.GetInterfaces ()) {
547 editorReference = table [iface];
548 if (editorReference != null)
553 if (editorReference == null)
556 if (editorReference is string)
557 editor = CreateEditor (Type.GetType ((string) editorReference), componentType);
558 else if (editorReference is Type)
559 editor = CreateEditor ((Type) editorReference, componentType);
560 else if (editorReference.GetType ().IsSubclassOf (editorBaseType))
561 editor = editorReference;
564 table [componentType] = editor;
569 public static object GetEditor (Type componentType, Type editorBaseType)
571 Type editorType = null;
572 object editor = null;
573 object [] atts = componentType.GetCustomAttributes (typeof(EditorAttribute), true);
575 if (atts != null && atts.Length != 0) {
576 foreach (EditorAttribute ea in atts) {
577 editorType = GetTypeFromName (null, ea.EditorTypeName);
578 if (editorType != null && editorType.IsSubclassOf(editorBaseType))
583 if (editorType != null)
584 editor = CreateEditor (editorType, componentType);
586 if (editorType == null || editor == null) {
588 // Make sure the editorBaseType's static constructor has been called,
589 // since that's where we're putting the initialization of its editor table.
591 System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (editorBaseType.TypeHandle);
594 editor = FindEditorInTable (componentType, editorBaseType, editors [editorBaseType] as Hashtable);
600 public static object GetEditor (object component, Type editorBaseType)
602 return GetEditor (component, editorBaseType, false);
605 [EditorBrowsable (EditorBrowsableState.Advanced)]
606 public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
608 if (component == null)
609 throw new ArgumentNullException ("component");
610 if (editorBaseType == null)
611 throw new ArgumentNullException ("editorBaseType");
613 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
614 return ((ICustomTypeDescriptor) component).GetEditor (editorBaseType);
616 object [] atts = component.GetType ().GetCustomAttributes (typeof (EditorAttribute), true);
617 if (atts.Length == 0)
619 string target = editorBaseType.AssemblyQualifiedName;
621 foreach (EditorAttribute ea in atts){
622 if (ea.EditorBaseTypeName == target){
623 Type t = Type.GetType (ea.EditorTypeName, true);
625 return Activator.CreateInstance (t);
631 public static EventDescriptorCollection GetEvents (object component)
633 return GetEvents (component, false);
636 public static EventDescriptorCollection GetEvents (Type componentType)
638 return GetEvents (componentType, null);
641 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes)
643 return GetEvents (component, attributes, false);
646 [EditorBrowsable (EditorBrowsableState.Advanced)]
647 public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
649 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
650 return ((ICustomTypeDescriptor) component).GetEvents ();
652 IComponent com = component as IComponent;
653 if (com != null && com.Site != null)
654 return GetComponentInfo (com).GetEvents ();
656 return GetTypeInfo (component.GetType()).GetEvents ();
660 public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
662 return GetTypeInfo (componentType).GetEvents (attributes);
665 [EditorBrowsable (EditorBrowsableState.Advanced)]
666 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
668 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
669 return ((ICustomTypeDescriptor) component).GetEvents (attributes);
671 IComponent com = component as IComponent;
672 if (com != null && com.Site != null)
673 return GetComponentInfo (com).GetEvents (attributes);
675 return GetTypeInfo (component.GetType()).GetEvents (attributes);
679 public static PropertyDescriptorCollection GetProperties (object component)
681 return GetProperties (component, false);
684 public static PropertyDescriptorCollection GetProperties (Type componentType)
686 return GetProperties (componentType, null);
689 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes)
691 return GetProperties (component, attributes, false);
694 public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
696 if (component == null)
697 return PropertyDescriptorCollection.Empty;
699 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
700 return ((ICustomTypeDescriptor) component).GetProperties (attributes);
702 IComponent com = component as IComponent;
703 if (com != null && com.Site != null)
704 return GetComponentInfo (com).GetProperties (attributes);
706 return GetTypeInfo (component.GetType()).GetProperties (attributes);
710 [EditorBrowsable (EditorBrowsableState.Advanced)]
711 public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
713 if (component == null)
714 return PropertyDescriptorCollection.Empty;
716 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
717 return ((ICustomTypeDescriptor) component).GetProperties ();
719 IComponent com = component as IComponent;
720 if (com != null && com.Site != null)
721 return GetComponentInfo (com).GetProperties ();
723 return GetTypeInfo (component.GetType()).GetProperties ();
727 public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
729 return GetTypeInfo (componentType).GetProperties (attributes);
732 [EditorBrowsable (EditorBrowsableState.Advanced)]
733 public static TypeDescriptionProvider GetProvider (object instance)
735 if (instance == null)
736 throw new ArgumentNullException ("instance");
738 TypeDescriptionProvider ret = null;
739 lock (componentDescriptionProvidersLock) {
740 LinkedList <TypeDescriptionProvider> plist;
741 WeakObjectWrapper instanceWrapper = new WeakObjectWrapper (instance);
743 if (componentDescriptionProviders.TryGetValue (instanceWrapper, out plist) && plist.Count > 0)
744 ret = plist.Last.Value;
746 instanceWrapper = null;
750 ret = GetProvider (instance.GetType ());
753 return new DefaultTypeDescriptionProvider ();
755 return new WrappedTypeDescriptionProvider (ret);
758 [EditorBrowsable (EditorBrowsableState.Advanced)]
759 public static TypeDescriptionProvider GetProvider (Type type)
762 throw new ArgumentNullException ("type");
764 TypeDescriptionProvider ret = null;
765 lock (typeDescriptionProvidersLock) {
766 LinkedList <TypeDescriptionProvider> plist;
768 while (!typeDescriptionProviders.TryGetValue (type, out plist)) {
770 type = type.BaseType;
775 if (plist != null && plist.Count > 0)
776 ret = plist.Last.Value;
780 return new DefaultTypeDescriptionProvider ();
782 return new WrappedTypeDescriptionProvider (ret);
785 [EditorBrowsable (EditorBrowsableState.Advanced)]
786 public static Type GetReflectionType (object instance)
788 if (instance == null)
789 throw new ArgumentNullException ("instance");
791 return instance.GetType ();
794 [EditorBrowsable (EditorBrowsableState.Advanced)]
795 public static Type GetReflectionType (Type type)
798 throw new ArgumentNullException ("type");
803 [MonoNotSupported("Associations not supported")]
804 [EditorBrowsable (EditorBrowsableState.Advanced)]
805 public static void CreateAssociation (object primary, object secondary)
807 throw new NotImplementedException ();
810 [MonoNotSupported ("Associations not supported")]
811 [EditorBrowsable (EditorBrowsableState.Advanced)]
812 public static object GetAssociation (Type type, object primary)
814 throw new NotImplementedException ();
817 [MonoNotSupported ("Associations not supported")]
818 [EditorBrowsable (EditorBrowsableState.Advanced)]
819 public static void RemoveAssociation (object primary, object secondary)
821 throw new NotImplementedException ();
824 [MonoNotSupported ("Associations not supported")]
825 [EditorBrowsable (EditorBrowsableState.Advanced)]
826 public static void RemoveAssociations (object primary)
828 throw new NotImplementedException ();
831 [EditorBrowsable (EditorBrowsableState.Advanced)]
832 public static void RemoveProvider (TypeDescriptionProvider provider, object instance)
834 if (provider == null)
835 throw new ArgumentNullException ("provider");
836 if (instance == null)
837 throw new ArgumentNullException ("instance");
839 //bool removed = false;
840 lock (componentDescriptionProvidersLock) {
841 LinkedList <TypeDescriptionProvider> plist;
842 WeakObjectWrapper instanceWrapper = new WeakObjectWrapper (instance);
844 if (componentDescriptionProviders.TryGetValue (instanceWrapper, out plist) && plist.Count > 0) {
845 RemoveProvider (provider, plist);
849 instanceWrapper = null;
852 var refreshed = Refreshed;
853 if (refreshed != null)
854 refreshed (new RefreshEventArgs (instance));
857 [EditorBrowsable (EditorBrowsableState.Advanced)]
858 public static void RemoveProvider (TypeDescriptionProvider provider, Type type)
860 if (provider == null)
861 throw new ArgumentNullException ("provider");
863 throw new ArgumentNullException ("type");
865 lock (typeDescriptionProvidersLock) {
866 LinkedList <TypeDescriptionProvider> plist;
868 if (typeDescriptionProviders.TryGetValue (type, out plist) && plist.Count > 0) {
869 RemoveProvider (provider, plist);
873 var refreshed = Refreshed;
874 if (refreshed != null)
875 refreshed (new RefreshEventArgs (type));
878 static void RemoveProvider (TypeDescriptionProvider provider, LinkedList <TypeDescriptionProvider> plist)
880 LinkedListNode <TypeDescriptionProvider> node = plist.Last;
881 LinkedListNode <TypeDescriptionProvider> first = plist.First;
882 TypeDescriptionProvider p;
893 node = node.Previous;
898 public static void SortDescriptorArray (IList infos)
900 string[] names = new string [infos.Count];
901 object[] values = new object [infos.Count];
902 for (int n=0; n<names.Length; n++) {
903 names[n] = ((MemberDescriptor)infos[n]).Name;
904 values[n] = infos[n];
906 Array.Sort (names, values);
908 foreach (object ob in values)
912 // well, ComObjectType is not implemented, but we don't support COM anyways ...
913 [Obsolete ("Use ComObjectType")]
914 public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
915 [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
916 get { return descriptorHandler; }
917 [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
918 set { descriptorHandler = value; }
921 public static void Refresh (Assembly assembly)
923 foreach (Type type in assembly.GetTypes())
927 public static void Refresh (Module module)
929 foreach (Type type in module.GetTypes())
933 public static void Refresh (object component)
935 lock (componentTable)
937 componentTable.Remove (component);
939 if (Refreshed != null) Refreshed (new RefreshEventArgs (component));
942 public static void Refresh (Type type)
946 typeTable.Remove (type);
948 if (Refreshed != null) Refreshed (new RefreshEventArgs (type));
951 static EventHandler onDispose;
953 static void OnComponentDisposed (object sender, EventArgs args)
955 lock (componentTable) {
956 componentTable.Remove (sender);
960 public static event RefreshEventHandler Refreshed;
962 internal static ComponentInfo GetComponentInfo (IComponent com)
964 lock (componentTable)
966 ComponentInfo ci = (ComponentInfo) componentTable [com];
968 if (onDispose == null)
969 onDispose = new EventHandler (OnComponentDisposed);
971 com.Disposed += onDispose;
972 ci = new ComponentInfo (com);
973 componentTable [com] = ci;
979 internal static TypeInfo GetTypeInfo (Type type)
983 TypeInfo ci = (TypeInfo) typeTable [type];
985 ci = new TypeInfo (type);
986 typeTable [type] = ci;
992 private static Type GetTypeFromName (IComponent component, string typeName)
995 if (component != null && component.Site != null) {
996 ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
998 type = resver.GetType (typeName);
1001 type = Type.GetType (typeName);
1005 sealed class AttributeProvider : TypeDescriptionProvider
1007 Attribute[] attributes;
1009 public AttributeProvider (Attribute[] attributes, TypeDescriptionProvider parent)
1012 this.attributes = attributes;
1015 public override ICustomTypeDescriptor GetTypeDescriptor (Type type, object instance)
1017 return new AttributeTypeDescriptor (base.GetTypeDescriptor (type, instance), attributes);
1020 sealed class AttributeTypeDescriptor : CustomTypeDescriptor
1022 Attribute[] attributes;
1024 public AttributeTypeDescriptor (ICustomTypeDescriptor parent, Attribute[] attributes)
1027 this.attributes = attributes;
1030 public override AttributeCollection GetAttributes ()
1032 AttributeCollection attrs = base.GetAttributes ();
1034 if (attrs != null && attrs.Count > 0)
1035 return AttributeCollection.FromExisting (attrs, attributes);
1037 return new AttributeCollection (attributes);
1042 sealed class WrappedTypeDescriptionProvider : TypeDescriptionProvider
1044 public TypeDescriptionProvider Wrapped { get; private set; }
1046 public WrappedTypeDescriptionProvider (TypeDescriptionProvider wrapped)
1051 public override object CreateInstance (IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
1053 TypeDescriptionProvider wrapped = Wrapped;
1055 if (wrapped == null)
1056 return base.CreateInstance (provider, objectType, argTypes, args);
1058 return wrapped.CreateInstance (provider, objectType, argTypes, args);
1061 public override IDictionary GetCache (object instance)
1063 TypeDescriptionProvider wrapped = Wrapped;
1065 if (wrapped == null)
1066 return base.GetCache (instance);
1068 return wrapped.GetCache (instance);
1071 public override ICustomTypeDescriptor GetExtendedTypeDescriptor (object instance)
1073 return new DefaultTypeDescriptor (this, null, instance);
1076 public override string GetFullComponentName (object component)
1078 TypeDescriptionProvider wrapped = Wrapped;
1080 if (wrapped == null)
1081 return base.GetFullComponentName (component);
1083 return wrapped.GetFullComponentName (component);
1086 public override Type GetReflectionType (Type type, object instance)
1088 TypeDescriptionProvider wrapped = Wrapped;
1090 if (wrapped == null)
1091 return base.GetReflectionType (type, instance);
1093 return wrapped.GetReflectionType (type, instance);
1096 public override ICustomTypeDescriptor GetTypeDescriptor (Type objectType, object instance)
1098 TypeDescriptionProvider wrapped = Wrapped;
1100 if (wrapped == null)
1101 return new DefaultTypeDescriptor (this, objectType, instance);
1103 return wrapped.GetTypeDescriptor (objectType, instance);
1107 // TODO: this needs more work
1108 sealed class DefaultTypeDescriptor : CustomTypeDescriptor
1110 TypeDescriptionProvider owner;
1114 public DefaultTypeDescriptor (TypeDescriptionProvider owner, Type objectType, object instance)
1117 this.objectType = objectType;
1118 this.instance = instance;
1121 public override AttributeCollection GetAttributes ()
1123 var wrapped = owner as WrappedTypeDescriptionProvider;
1125 if (wrapped != null)
1126 return wrapped.Wrapped.GetTypeDescriptor (objectType, instance).GetAttributes ();
1128 if (instance != null)
1129 return TypeDescriptor.GetAttributes (instance, false);
1131 if (objectType != null)
1132 return TypeDescriptor.GetTypeInfo (objectType).GetAttributes ();
1134 return base.GetAttributes ();
1137 public override string GetClassName ()
1139 var wrapped = owner as WrappedTypeDescriptionProvider;
1141 if (wrapped != null)
1142 return wrapped.Wrapped.GetTypeDescriptor (objectType, instance).GetClassName ();
1144 return base.GetClassName ();
1147 public override PropertyDescriptor GetDefaultProperty ()
1149 var wrapped = owner as WrappedTypeDescriptionProvider;
1151 if (wrapped != null)
1152 return wrapped.Wrapped.GetTypeDescriptor (objectType, instance).GetDefaultProperty ();
1154 PropertyDescriptor ret;
1155 if (objectType != null)
1156 ret = TypeDescriptor.GetTypeInfo (objectType).GetDefaultProperty ();
1157 else if (instance != null)
1158 ret = TypeDescriptor.GetTypeInfo (instance.GetType ()).GetDefaultProperty ();
1160 ret = base.GetDefaultProperty ();
1165 public override PropertyDescriptorCollection GetProperties ()
1167 var wrapped = owner as WrappedTypeDescriptionProvider;
1169 if (wrapped != null)
1170 return wrapped.Wrapped.GetTypeDescriptor (objectType, instance).GetProperties ();
1172 if (instance != null)
1173 return TypeDescriptor.GetProperties (instance, null, false);
1175 if (objectType != null)
1176 return TypeDescriptor.GetTypeInfo (objectType).GetProperties (null);
1178 return base.GetProperties ();
1182 sealed class DefaultTypeDescriptionProvider : TypeDescriptionProvider
1184 public DefaultTypeDescriptionProvider ()
1188 public override ICustomTypeDescriptor GetExtendedTypeDescriptor (object instance)
1190 return new DefaultTypeDescriptor (this, null, instance);
1193 public override ICustomTypeDescriptor GetTypeDescriptor (Type objectType, object instance)
1195 return new DefaultTypeDescriptor (this, objectType, instance);
1200 internal abstract class Info
1203 EventDescriptor _defaultEvent;
1204 bool _gotDefaultEvent;
1205 PropertyDescriptor _defaultProperty;
1206 bool _gotDefaultProperty;
1207 AttributeCollection _attributes;
1209 public Info (Type infoType)
1211 _infoType = infoType;
1214 public abstract AttributeCollection GetAttributes ();
1215 public abstract EventDescriptorCollection GetEvents ();
1216 public abstract PropertyDescriptorCollection GetProperties ();
1218 public Type InfoType
1220 get { return _infoType; }
1223 public EventDescriptorCollection GetEvents (Attribute[] attributes)
1225 EventDescriptorCollection evs = GetEvents ();
1226 if (attributes == null)
1229 return evs.Filter (attributes);
1232 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
1234 PropertyDescriptorCollection props = GetProperties ();
1235 if (attributes == null)
1238 return props.Filter (attributes);
1241 public EventDescriptor GetDefaultEvent ()
1243 if (_gotDefaultEvent)
1244 return _defaultEvent;
1246 DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
1247 if (attr == null || attr.Name == null)
1248 _defaultEvent = null;
1250 EventDescriptorCollection events = GetEvents ();
1251 _defaultEvent = events [attr.Name];
1253 // In our test case (TypeDescriptorTest.TestGetDefaultEvent), we have
1254 // a scenario where a custom filter adds the DefaultEventAttribute,
1255 // but its FilterEvents method removes the event the
1256 // DefaultEventAttribute applied to. .NET 1.x accepts this and returns
1257 // the *other* event defined in the class.
1259 // Consequently, we know we have a DefaultEvent, but we need to check
1260 // and ensure that the requested event is unfiltered. If it is, just
1261 // grab the first element in the collection.
1262 if (_defaultEvent == null && events.Count > 0)
1263 _defaultEvent = events [0];
1266 _gotDefaultEvent = true;
1267 return _defaultEvent;
1270 public PropertyDescriptor GetDefaultProperty ()
1272 if (_gotDefaultProperty)
1273 return _defaultProperty;
1275 DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
1276 if (attr == null || attr.Name == null)
1277 _defaultProperty = null;
1279 PropertyDescriptorCollection properties = GetProperties ();
1280 _defaultProperty = properties[attr.Name];
1282 _gotDefaultProperty = true;
1283 return _defaultProperty;
1286 protected AttributeCollection GetAttributes (IComponent comp)
1288 if (_attributes != null)
1292 ArrayList attributesList = new ArrayList ();
1294 // 1) Attributes of the type
1295 foreach (Attribute attribute in _infoType.GetCustomAttributes (false))
1296 attributesList.Add (attribute);
1298 // 2) Attributes of the base types
1299 Type baseType = _infoType.BaseType;
1300 while (baseType != null && baseType != typeof (object)) {
1301 foreach (Attribute attribute in baseType.GetCustomAttributes (false))
1302 attributesList.Add (attribute);
1303 baseType = baseType.BaseType;
1306 // 3) Attributes of the type's implemented interfaces and their interfaces as well
1307 foreach (Type inface in _infoType.GetInterfaces ())
1308 foreach (Attribute attribute in TypeDescriptor.GetAttributes (inface))
1309 attributesList.Add (attribute);
1311 // Filter out duplicate attributes, so that the base types have higher precedence
1312 // than the interfaces and the type higher than both.
1313 Hashtable attributesTable = new Hashtable ();
1314 for (int i = attributesList.Count - 1; i >= 0; i--) {
1315 Attribute attribute = (Attribute)attributesList[i];
1316 attributesTable[attribute.TypeId] = attribute;
1319 if (comp != null && comp.Site != null)
1321 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) comp.Site.GetService (typeof(ITypeDescriptorFilterService));
1323 cache = filter.FilterAttributes (comp, attributesTable);
1326 Attribute[] attributes = new Attribute[attributesTable.Values.Count];
1327 attributesTable.Values.CopyTo (attributes, 0);
1328 AttributeCollection attCol = new AttributeCollection (attributes);
1330 _attributes = attCol;
1335 internal class ComponentInfo : Info
1337 IComponent _component;
1338 EventDescriptorCollection _events;
1339 PropertyDescriptorCollection _properties;
1341 public ComponentInfo (IComponent component): base (component.GetType())
1343 _component = component;
1346 public override AttributeCollection GetAttributes ()
1348 return base.GetAttributes (_component);
1351 public override EventDescriptorCollection GetEvents ()
1353 if (_events != null)
1357 EventInfo[] events = _component.GetType().GetEvents ();
1358 Hashtable t = new Hashtable ();
1359 foreach (EventInfo ev in events)
1360 t [ev.Name] = new ReflectionEventDescriptor (ev);
1362 if (_component.Site != null)
1364 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
1366 cache = filter.FilterEvents (_component, t);
1369 ArrayList atts = new ArrayList ();
1370 atts.AddRange (t.Values);
1371 EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
1372 if (cache) _events = attCol;
1376 public override PropertyDescriptorCollection GetProperties ()
1378 if (_properties != null)
1382 PropertyInfo[] props = _component.GetType().GetProperties (BindingFlags.Instance | BindingFlags.Public);
1383 Hashtable t = new Hashtable ();
1384 for (int i = props.Length-1; i >= 0; i--)
1385 t [props[i].Name] = new ReflectionPropertyDescriptor (props[i]);
1387 if (_component.Site != null)
1389 ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
1391 cache = filter.FilterProperties (_component, t);
1394 PropertyDescriptor[] descriptors = new PropertyDescriptor[t.Values.Count];
1395 t.Values.CopyTo (descriptors, 0);
1396 PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (descriptors, true);
1398 _properties = attCol;
1403 internal class TypeInfo : Info
1405 EventDescriptorCollection _events;
1406 PropertyDescriptorCollection _properties;
1408 public TypeInfo (Type t): base (t)
1412 public override AttributeCollection GetAttributes ()
1414 return base.GetAttributes (null);
1417 public override EventDescriptorCollection GetEvents ()
1419 if (_events != null)
1422 EventInfo[] events = InfoType.GetEvents ();
1423 EventDescriptor[] descs = new EventDescriptor [events.Length];
1424 for (int n=0; n<events.Length; n++)
1425 descs [n] = new ReflectionEventDescriptor (events[n]);
1427 _events = new EventDescriptorCollection (descs);
1431 public override PropertyDescriptorCollection GetProperties ()
1433 if (_properties != null)
1436 Hashtable propertiesHash = new Hashtable (); // name - null
1437 ArrayList propertiesList = new ArrayList (); // propertydescriptors
1438 Type currentType = InfoType;
1439 // Getting properties type by type, because in the case of a property in the child type, where
1440 // the "new" keyword is used and also the return type is changed Type.GetProperties returns
1441 // also the parent property.
1443 // Note that we also have to preserve the properties order here.
1445 while (currentType != null && currentType != typeof (object)) {
1446 PropertyInfo[] props = currentType.GetProperties (BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
1447 foreach (PropertyInfo property in props) {
1448 if (property.GetIndexParameters ().Length == 0 &&
1450 !propertiesHash.ContainsKey (property.Name)) {
1451 propertiesList.Add (new ReflectionPropertyDescriptor (property));
1452 propertiesHash.Add (property.Name, null);
1455 currentType = currentType.BaseType;
1458 _properties = new PropertyDescriptorCollection ((PropertyDescriptor[]) propertiesList.ToArray (typeof (PropertyDescriptor)), true);
1464 // In .net this class seems to be a dummy and empty class
1465 // used to represent internally any extender provider associated with
1466 // all the interfaces.
1467 sealed class TypeDescriptorInterface