2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System / System.ComponentModel / TypeDescriptor.cs
blob35df4f0410e2b3420fa350183039717c37bd10b0
1 //
2 // System.ComponentModel.TypeDescriptor.cs
3 //
4 // Authors:
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 // Ivan N. Zlatev (contact@i-nz.net)
8 //
9 //
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:
23 //
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 //
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 #if NET_2_0
43 using System.Collections.Generic;
44 #endif
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;
58 #if NET_2_0
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 ());
70 #endif
71 private TypeDescriptor ()
75 #if NET_2_0
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)
85 if (instance == null)
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);
93 return ret;
96 [EditorBrowsable (EditorBrowsableState.Advanced)]
97 public static TypeDescriptionProvider AddAttributes (Type type, params Attribute [] attributes)
99 if (type == null)
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);
107 return ret;
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;
129 Refresh (instance);
133 [EditorBrowsable (EditorBrowsableState.Advanced)]
134 public static void AddProvider (TypeDescriptionProvider provider, Type type)
136 if (provider == null)
137 throw new ArgumentNullException ("provider");
138 if (type == null)
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);
150 Refresh (type);
154 [MonoTODO]
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);
173 return instance;
175 #endif
177 #if NET_2_0
178 [EditorBrowsable (EditorBrowsableState.Advanced)]
179 #endif
180 #if !NET_2_1
181 public
182 #else
183 internal
184 #endif
185 static void AddEditorTable (Type editorBaseType, Hashtable table)
187 if (editorBaseType == null)
188 throw new ArgumentNullException ("editorBaseType");
190 if (editors == null)
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);
211 return null;
214 [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
215 public static EventDescriptor CreateEvent (Type componentType,
216 string name,
217 Type type,
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,
233 string name,
234 Type type,
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);
261 #if NET_2_0
262 [EditorBrowsable (EditorBrowsableState.Advanced)]
263 #endif
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 ();
271 } else {
272 IComponent com = component as IComponent;
273 if (com != null && com.Site != null)
274 return GetComponentInfo (com).GetAttributes ();
275 else
276 return GetTypeInfo (component.GetType()).GetAttributes ();
280 public static string GetClassName (object component)
282 return GetClassName (component, false);
285 #if NET_2_0
286 [EditorBrowsable (EditorBrowsableState.Advanced)]
287 #endif
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 ();
295 if (res == null)
296 res = ((ICustomTypeDescriptor) component).GetComponentName ();
297 if (res == null)
298 res = component.GetType ().FullName;
299 return res;
300 } else {
301 return component.GetType ().FullName;
305 public static string GetComponentName (object component)
307 return GetComponentName (component, false);
310 #if NET_2_0
311 [EditorBrowsable (EditorBrowsableState.Advanced)]
312 #endif
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 ();
320 } else {
321 IComponent c = component as IComponent;
322 if (c != null && c.Site != null)
323 return c.Site.Name;
324 #if NET_2_0
325 return null;
326 #else
327 return component.GetType().Name;
328 #endif
332 #if NET_2_0
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 ();
344 #endif
346 public static TypeConverter GetConverter (object component)
348 return GetConverter (component, false);
351 #if NET_2_0
352 [EditorBrowsable (EditorBrowsableState.Advanced)]
353 #endif
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 ();
362 else {
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) });
373 if (ci != null)
374 return (TypeConverter) ci.Invoke (new object[] { component.GetType () });
375 else
376 return (TypeConverter) Activator.CreateInstance (converterType);
377 } else
378 return null;
382 private static ArrayList DefaultConverters
384 get {
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)
419 if (type == null)
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) });
432 if (ci != null)
433 return (TypeConverter) ci.Invoke (new object[] { type });
434 else
435 return (TypeConverter) Activator.CreateInstance (converterType);
437 else
438 return null;
441 private static Type FindDefaultConverterType (Type type)
443 Type converterType = null;
444 if (type != null) {
445 #if NET_2_0
446 if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
447 return typeof(NullableConverter);
448 #endif
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;
463 break;
466 baseType = baseType.BaseType;
469 if (converterType == null) {
470 if (type != null && type.IsInterface)
471 converterType = typeof (ReferenceConverter);
472 else
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);
489 #if NET_2_0
490 [EditorBrowsable (EditorBrowsableState.Advanced)]
491 #endif
492 public static EventDescriptor GetDefaultEvent (object component, bool noCustomTypeDesc)
494 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
495 return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
496 else {
497 IComponent com = component as IComponent;
498 if (com != null && com.Site != null)
499 return GetComponentInfo (com).GetDefaultEvent ();
500 else
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);
515 #if NET_2_0
516 [EditorBrowsable (EditorBrowsableState.Advanced)]
517 #endif
518 public static PropertyDescriptor GetDefaultProperty (object component, bool noCustomTypeDesc)
520 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
521 return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
522 else {
523 IComponent com = component as IComponent;
524 if (com != null && com.Site != null)
525 return GetComponentInfo (com).GetDefaultProperty ();
526 else
527 return GetTypeInfo (component.GetType()).GetDefaultProperty ();
531 internal static object CreateEditor (Type t, Type componentType)
533 if (t == null)
534 return null;
536 try {
537 return Activator.CreateInstance (t);
538 } catch {}
540 try {
541 return Activator.CreateInstance (t, new object [] {componentType});
542 } catch {}
544 return null;
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)
553 return null;
555 Type ct = componentType;
556 while (ct != null) {
557 editorReference = table [ct];
558 if (editorReference != null)
559 break;
560 ct = ct.BaseType;
563 if (editorReference == null) {
564 foreach (Type iface in componentType.GetInterfaces ()) {
565 editorReference = table [iface];
566 if (editorReference != null)
567 break;
571 if (editorReference == null)
572 return 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;
581 if (editor != null)
582 table [componentType] = editor;
584 return 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))
597 break;
601 if (editorType != null)
602 editor = CreateEditor (editorType, componentType);
604 if (editorType == null || editor == null) {
605 #if !TARGET_JVM
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);
610 #endif
611 if (editors != null)
612 editor = FindEditorInTable (componentType, editorBaseType, editors [editorBaseType] as Hashtable);
615 return editor;
618 public static object GetEditor (object component, Type editorBaseType)
620 return GetEditor (component, editorBaseType, false);
623 #if NET_2_0
624 [EditorBrowsable (EditorBrowsableState.Advanced)]
625 #endif
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)
638 return null;
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);
648 return null;
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);
666 #if NET_2_0
667 [EditorBrowsable (EditorBrowsableState.Advanced)]
668 #endif
669 public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
671 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
672 return ((ICustomTypeDescriptor) component).GetEvents ();
673 else {
674 IComponent com = component as IComponent;
675 if (com != null && com.Site != null)
676 return GetComponentInfo (com).GetEvents ();
677 else
678 return GetTypeInfo (component.GetType()).GetEvents ();
682 public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
684 return GetTypeInfo (componentType).GetEvents (attributes);
687 #if NET_2_0
688 [EditorBrowsable (EditorBrowsableState.Advanced)]
689 #endif
690 public static EventDescriptorCollection GetEvents (object component, Attribute [] attributes, bool noCustomTypeDesc)
692 if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
693 return ((ICustomTypeDescriptor) component).GetEvents (attributes);
694 else {
695 IComponent com = component as IComponent;
696 if (com != null && com.Site != null)
697 return GetComponentInfo (com).GetEvents (attributes);
698 else
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);
725 else {
726 IComponent com = component as IComponent;
727 if (com != null && com.Site != null)
728 return GetComponentInfo (com).GetProperties (attributes);
729 else
730 return GetTypeInfo (component.GetType()).GetProperties (attributes);
734 #if NET_2_0
735 [EditorBrowsable (EditorBrowsableState.Advanced)]
736 #endif
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 ();
744 else {
745 IComponent com = component as IComponent;
746 if (com != null && com.Site != null)
747 return GetComponentInfo (com).GetProperties ();
748 else
749 return GetTypeInfo (component.GetType()).GetProperties ();
753 public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
755 return GetTypeInfo (componentType).GetProperties (attributes);
758 #if NET_2_0
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;
776 if (ret == null)
777 ret = GetProvider (instance.GetType ());
779 if (ret == null)
780 return new DefaultTypeDescriptionProvider ();
781 else
782 return new WrappedTypeDescriptionProvider (ret);
785 [EditorBrowsable (EditorBrowsableState.Advanced)]
786 public static TypeDescriptionProvider GetProvider (Type type)
788 if (type == null)
789 throw new ArgumentNullException ("type");
791 TypeDescriptionProvider ret = null;
792 lock (typeDescriptionProvidersLock) {
793 LinkedList <TypeDescriptionProvider> plist;
795 while (!typeDescriptionProviders.TryGetValue (type, out plist)) {
796 plist = null;
797 type = type.BaseType;
798 if (type == null)
799 break;
802 if (plist != null && plist.Count > 0)
803 ret = plist.Last.Value;
806 if (ret == null)
807 return new DefaultTypeDescriptionProvider ();
808 else
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)
824 if (type == null)
825 throw new ArgumentNullException ("type");
827 return 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);
873 //removed = true;
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");
889 if (type == null)
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;
911 do {
912 p = node.Value;
913 if (p == provider) {
914 plist.Remove (node);
915 break;
917 if (node == first)
918 break;
920 node = node.Previous;
922 } while (true);
924 #endif
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);
935 infos.Clear();
936 foreach (object ob in values)
937 infos.Add (ob);
940 #if NET_2_0
941 // well, ComObjectType is not implemented, but we don't support COM anyways ...
942 [Obsolete ("Use ComObjectType")]
943 #endif
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())
954 Refresh (type);
957 public static void Refresh (Module module)
959 foreach (Type type in module.GetTypes())
960 Refresh (type);
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)
974 lock (typeTable)
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];
997 if (ci == null) {
998 if (onDispose == null)
999 onDispose = new EventHandler (OnComponentDisposed);
1001 com.Disposed += onDispose;
1002 ci = new ComponentInfo (com);
1003 componentTable [com] = ci;
1005 return ci;
1009 internal static TypeInfo GetTypeInfo (Type type)
1011 lock (typeTable)
1013 TypeInfo ci = (TypeInfo) typeTable [type];
1014 if (ci == null) {
1015 ci = new TypeInfo (type);
1016 typeTable [type] = ci;
1018 return ci;
1022 private static Type GetTypeFromName (IComponent component, string typeName)
1024 Type type = null;
1025 if (component != null && component.Site != null) {
1026 ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
1027 if (resver != null)
1028 type = resver.GetType (typeName);
1030 if (type == null)
1031 type = Type.GetType (typeName);
1032 return type;
1035 #if NET_2_0
1036 sealed class AttributeProvider : TypeDescriptionProvider
1038 Attribute[] attributes;
1040 public AttributeProvider (Attribute[] attributes, TypeDescriptionProvider parent)
1041 : base (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)
1056 : base (parent)
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);
1067 else
1068 return new AttributeCollection (attributes);
1073 sealed class WrappedTypeDescriptionProvider : TypeDescriptionProvider
1075 public TypeDescriptionProvider Wrapped { get; private set; }
1077 public WrappedTypeDescriptionProvider (TypeDescriptionProvider wrapped)
1079 Wrapped = 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;
1142 Type objectType;
1143 object instance;
1145 public DefaultTypeDescriptor (TypeDescriptionProvider owner, Type objectType, object instance)
1147 this.owner = owner;
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 ();
1190 else
1191 ret = base.GetDefaultProperty ();
1193 return ret;
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);
1229 #endif
1232 internal abstract class Info
1234 Type _infoType;
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)
1259 return evs;
1260 else
1261 return evs.Filter (attributes);
1264 public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
1266 PropertyDescriptorCollection props = GetProperties ();
1267 if (attributes == null)
1268 return props;
1269 else
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;
1281 else {
1282 EventDescriptorCollection events = GetEvents ();
1283 _defaultEvent = events [attr.Name];
1284 #if !NET_2_0
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];
1296 #endif
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;
1310 else {
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)
1321 return _attributes;
1323 bool cache = true;
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));
1354 if (filter != null)
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);
1361 if (cache)
1362 _attributes = attCol;
1363 return 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)
1386 return _events;
1388 bool cache = true;
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));
1397 if (filter != null)
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;
1405 return attCol;
1408 public override PropertyDescriptorCollection GetProperties ()
1410 if (_properties != null)
1411 return _properties;
1413 bool cache = true;
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));
1422 if (filter != null)
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);
1429 if (cache)
1430 _properties = attCol;
1431 return 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)
1452 return _events;
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);
1460 return _events;
1463 public override PropertyDescriptorCollection GetProperties ()
1465 if (_properties != null)
1466 return _properties;
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 &&
1481 property.CanRead &&
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);
1491 return _properties;