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);