1 //------------------------------------------------------------------------------
2 // <copyright file="TypeDescriptor.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
9 namespace System
.ComponentModel
11 using System
.Runtime
.Serialization
.Formatters
;
12 using System
.Threading
;
13 using System
.Runtime
.Remoting
.Activation
;
14 using System
.Runtime
.InteropServices
;
15 using System
.Diagnostics
;
17 using CodeAccessPermission
= System
.Security
.CodeAccessPermission
;
18 using System
.Security
;
19 using System
.Security
.Permissions
;
20 using System
.Collections
;
21 using System
.Collections
.Specialized
;
22 using System
.Globalization
;
24 using System
.Reflection
;
25 using Microsoft
.Win32
;
26 using System
.ComponentModel
.Design
;
27 using System
.Diagnostics
.CodeAnalysis
;
28 using System
.Runtime
.Versioning
;
31 /// Provides information about the properties and events
32 /// for a component. This class cannot be inherited.
34 [HostProtection(SharedState
= true)]
35 public sealed class TypeDescriptor
37 // Note: this is initialized at class load because we
38 // lock on it for thread safety. It is used from nearly
39 // every call to this class, so it will be created soon after
41 private static WeakHashtable _providerTable
= new WeakHashtable(); // mapping of type or object hash to a provider list
42 private static Hashtable _providerTypeTable
= new Hashtable(); // A direct mapping from type to provider.
43 private static volatile Hashtable _defaultProviders
= new Hashtable(); // A table of type -> default provider to track DefaultTypeDescriptionProviderAttributes.
44 private static volatile WeakHashtable _associationTable
;
45 private static int _metadataVersion
; // a version stamp for our metadata. Used by property descriptors to know when to rebuild
49 // This is an index that we use to create a unique name for a property in the
50 // event of a name collision. The only time we should use this is when
51 // a name collision happened on an extender property that has no site or
52 // no name on its site. Should be very rare.
53 private static int _collisionIndex
;
55 private static BooleanSwitch TraceDescriptor
= new BooleanSwitch("TypeDescriptor", "Debug TypeDescriptor.");
58 private static BooleanSwitch EnableValidation
= new BooleanSwitch("EnableValidation", "Enable type descriptor Whidbey->RTM validation");
61 // For each stage of our filtering pipeline, the pipeline needs to know
62 // what it is filtering.
63 private const int PIPELINE_ATTRIBUTES
= 0x00;
64 private const int PIPELINE_PROPERTIES
= 0x01;
65 private const int PIPELINE_EVENTS
= 0x02;
67 // And each stage of the pipeline needs to have its own
68 // keys for its cache table. We use guids because they
69 // are unique and fast to compare. The order for each of
70 // these keys must match the Id's of the filter type above.
71 private static readonly Guid
[] _pipelineInitializeKeys
= new Guid
[]
73 Guid
.NewGuid(), // attributes
74 Guid
.NewGuid(), // properties
75 Guid
.NewGuid() // events
78 private static readonly Guid
[] _pipelineMergeKeys
= new Guid
[]
80 Guid
.NewGuid(), // attributes
81 Guid
.NewGuid(), // properties
82 Guid
.NewGuid() // events
85 private static readonly Guid
[] _pipelineFilterKeys
= new Guid
[]
87 Guid
.NewGuid(), // attributes
88 Guid
.NewGuid(), // properties
89 Guid
.NewGuid() // events
92 private static readonly Guid
[] _pipelineAttributeFilterKeys
= new Guid
[]
94 Guid
.NewGuid(), // attributes
95 Guid
.NewGuid(), // properties
96 Guid
.NewGuid() // events
99 private static object _internalSyncObject
= new object();
101 private TypeDescriptor()
108 [Obsolete("This property has been deprecated. Use a type description provider to supply type information for COM types instead. http://go.microsoft.com/fwlink/?linkid=14202")]
109 public static IComNativeDescriptorHandler ComNativeDescriptorHandler
111 [PermissionSetAttribute(SecurityAction
.LinkDemand
, Name
="FullTrust")]
114 TypeDescriptionNode node
= NodeFor(ComObjectType
);
115 ComNativeDescriptionProvider provider
= null;
119 provider
= node
.Provider
as ComNativeDescriptionProvider
;
122 while(node
!= null && provider
== null);
124 if (provider
!= null)
126 return provider
.Handler
;
131 [PermissionSetAttribute(SecurityAction
.LinkDemand
, Name
="FullTrust")]
134 TypeDescriptionNode node
= NodeFor(ComObjectType
);
136 while (node
!= null && !(node
.Provider
is ComNativeDescriptionProvider
))
143 AddProvider(new ComNativeDescriptionProvider(value), ComObjectType
);
147 ComNativeDescriptionProvider provider
= (ComNativeDescriptionProvider
)node
.Provider
;
148 provider
.Handler
= value;
155 /// This property returns a Type object that can be passed to the various
156 /// AddProvider methods to define a type description provider for COM types.
158 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
159 public static Type ComObjectType
163 return typeof(TypeDescriptorComObject
);
168 /// This property returns a Type object that can be passed to the various
169 /// AddProvider methods to define a type description provider for interface types.
171 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
172 public static Type InterfaceType
176 return typeof(TypeDescriptorInterface
);
181 /// This value increments each time someone refreshes or changes metadata.
183 internal static int MetadataVersion
{
185 return _metadataVersion
;
189 /// <include file='doc\TypeDescriptor.uex' path='docs/doc[@for="TypeDescriptor.Refreshed"]/*' />
191 /// Occurs when Refreshed is raised for a component.
193 public static event RefreshEventHandler Refreshed
;
196 /// The AddAttributes method allows you to add class-level attributes for a
197 /// type or an instance. This method simply implements a type description provider
198 /// that merges the provided attributes with the attributes that already exist on
199 /// the class. This is a short cut for such a behavior. Adding additional
200 /// attributes is common need for applications using the Windows Forms property
201 /// window. The return value form AddAttributes is the TypeDescriptionProvider
202 /// that was used to add the attributes. This provider can later be passed to
203 /// RemoveProvider if the added attributes are no longer needed.
205 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
206 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
207 public static TypeDescriptionProvider
AddAttributes(Type type
, params Attribute
[] attributes
) {
210 throw new ArgumentNullException("type");
213 if (attributes
== null) {
214 throw new ArgumentNullException("attributes");
217 TypeDescriptionProvider existingProvider
= GetProvider(type
);
218 TypeDescriptionProvider provider
= new AttributeProvider(existingProvider
, attributes
);
219 TypeDescriptor
.AddProvider(provider
, type
);
224 /// The AddAttributes method allows you to add class-level attributes for a
225 /// type or an instance. This method simply implements a type description provider
226 /// that merges the provided attributes with the attributes that already exist on
227 /// the class. This is a short cut for such a behavior. Adding additional
228 /// attributes is common need for applications using the Windows Forms property
229 /// window. The return value form AddAttributes is the TypeDescriptionProvider
230 /// that was used to add the attributes. This provider can later be passed to
231 /// RemoveProvider if the added attributes are no longer needed.
233 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
234 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
235 public static TypeDescriptionProvider
AddAttributes(object instance
, params Attribute
[] attributes
) {
237 if (instance
== null) {
238 throw new ArgumentNullException("instance");
241 if (attributes
== null) {
242 throw new ArgumentNullException("attributes");
245 TypeDescriptionProvider existingProvider
= GetProvider(instance
);
246 TypeDescriptionProvider provider
= new AttributeProvider(existingProvider
, attributes
);
247 TypeDescriptor
.AddProvider(provider
, instance
);
253 /// Adds an editor table for the given editor base type.
254 /// ypically, editors are specified as metadata on an object. If no metadata for a
255 /// equested editor base type can be found on an object, however, the
256 /// ypeDescriptor will search an editor
257 /// able for the editor type, if one can be found.
259 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
260 public static void AddEditorTable(Type editorBaseType
, Hashtable table
)
262 ReflectTypeDescriptionProvider
.AddEditorTable(editorBaseType
, table
);
266 /// Adds a type description provider that will be called on to provide
267 /// type and instance information for any object that is of, or a subtype
268 /// of, the provided type. Type can be any type, including interfaces.
269 /// For example, to provide custom type and instance information for all
270 /// components, you would pass typeof(IComponent). Passing typeof(object)
271 /// will cause the provider to be called to provide type information for
274 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
275 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
276 public static void AddProvider(TypeDescriptionProvider provider
, Type type
)
278 if (provider
== null)
280 throw new ArgumentNullException("provider");
285 throw new ArgumentNullException("type");
290 // Get the root node, hook it up, and stuff it back into
291 // the provider cache.
292 TypeDescriptionNode node
= NodeFor(type
, true);
293 TypeDescriptionNode head
= new TypeDescriptionNode(provider
);
295 _providerTable
[type
] = head
;
296 _providerTypeTable
.Clear();
303 /// Adds a type description provider that will be called on to provide
304 /// type information for a single object instance. A provider added
305 /// using this method will never have its CreateInstance method called
306 /// because the instance already exists. This method does not prevent
307 /// the object from finalizing.
309 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
310 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
311 public static void AddProvider(TypeDescriptionProvider provider
, object instance
)
313 if (provider
== null)
315 throw new ArgumentNullException("provider");
318 if (instance
== null)
320 throw new ArgumentNullException("instance");
324 // Get the root node, hook it up, and stuff it back into
325 // the provider cache.
328 refreshNeeded
= _providerTable
.ContainsKey(instance
);
329 TypeDescriptionNode node
= NodeFor(instance
, true);
330 TypeDescriptionNode head
= new TypeDescriptionNode(provider
);
332 _providerTable
.SetWeak(instance
, head
);
333 _providerTypeTable
.Clear();
338 Refresh(instance
, false);
343 /// Adds a type description provider that will be called on to provide
344 /// type and instance information for any object that is of, or a subtype
345 /// of, the provided type. Type can be any type, including interfaces.
346 /// For example, to provide custom type and instance information for all
347 /// components, you would pass typeof(IComponent). Passing typeof(object)
348 /// will cause the provider to be called to provide type information for
351 /// This method can be called from partially trusted code. If
352 /// <see cref="TypeDescriptorPermissionFlags.RestrictedRegistrationAccess"/>
353 /// is defined, the caller can register a provider for the specified type
354 /// if it's also partially trusted.
356 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
357 public static void AddProviderTransparent(TypeDescriptionProvider provider
, Type type
)
359 if (provider
== null)
361 throw new ArgumentNullException("provider");
366 throw new ArgumentNullException("type");
369 PermissionSet typeDescriptorPermission
= new PermissionSet(PermissionState
.None
);
370 typeDescriptorPermission
.AddPermission(new TypeDescriptorPermission(TypeDescriptorPermissionFlags
.RestrictedRegistrationAccess
));
372 PermissionSet targetPermissions
= type
.Assembly
.PermissionSet
;
373 targetPermissions
= targetPermissions
.Union(typeDescriptorPermission
);
375 targetPermissions
.Demand();
377 AddProvider(provider
, type
);
381 /// Adds a type description provider that will be called on to provide
382 /// type information for a single object instance. A provider added
383 /// using this method will never have its CreateInstance method called
384 /// because the instance already exists. This method does not prevent
385 /// the object from finalizing.
387 /// This method can be called from partially trusted code. If
388 /// <see cref="TypeDescriptorPermissionFlags.RestrictedRegistrationAccess"/>
389 /// is defined, the caller can register a provider for the specified instance
390 /// if its type is also partially trusted.
392 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
393 public static void AddProviderTransparent(TypeDescriptionProvider provider
, object instance
)
395 if (provider
== null)
397 throw new ArgumentNullException("provider");
400 if (instance
== null)
402 throw new ArgumentNullException("instance");
405 Type type
= instance
.GetType();
407 PermissionSet typeDescriptorPermission
= new PermissionSet(PermissionState
.None
);
408 typeDescriptorPermission
.AddPermission(new TypeDescriptorPermission(TypeDescriptorPermissionFlags
.RestrictedRegistrationAccess
));
410 PermissionSet targetPermissions
= type
.Assembly
.PermissionSet
;
411 targetPermissions
= targetPermissions
.Union(typeDescriptorPermission
);
413 targetPermissions
.Demand();
415 AddProvider(provider
, instance
);
419 /// This method verifies that we have checked for the presence
420 /// of a default type description provider attribute for the
423 //See security note below
424 [SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts")]
425 private static void CheckDefaultProvider(Type type
)
427 if (_defaultProviders
== null)
429 lock (_internalSyncObject
)
431 if (_defaultProviders
== null)
433 _defaultProviders
= new Hashtable();
438 if (_defaultProviders
.ContainsKey(type
))
443 lock (_internalSyncObject
)
445 if (_defaultProviders
.ContainsKey(type
))
450 // Immediately clear this. If we find a default provider
451 // and it starts messing around with type information,
452 // this could infinitely recurse.
454 _defaultProviders
[type
] = null;
457 // Always use core reflection when checking for
458 // the default provider attribute. If there is a
459 // provider, we probably don't want to build up our
460 // own cache state against the type. There shouldn't be
461 // more than one of these, but walk anyway. Walk in
462 // reverse order so that the most derived takes precidence.
464 object[] attrs
= type
.GetCustomAttributes(typeof(TypeDescriptionProviderAttribute
), false);
465 bool providerAdded
= false;
466 for (int idx
= attrs
.Length
- 1; idx
>= 0; idx
--)
468 TypeDescriptionProviderAttribute pa
= (TypeDescriptionProviderAttribute
)attrs
[idx
];
469 Type providerType
= Type
.GetType(pa
.TypeName
);
470 if (providerType
!= null && typeof(TypeDescriptionProvider
).IsAssignableFrom(providerType
))
472 TypeDescriptionProvider prov
;
474 // Security Note: TypeDescriptionProviders are similar to TypeConverters and UITypeEditors in the
475 // sense that they provide a public API while not necessarily being public themselves. As such,
476 // we need to allow instantiation of internal TypeDescriptionProviders. See the thread attached
477 // to VSWhidbey #500522 for a more detailed discussion.
479 IntSecurity
.FullReflection
.Assert();
482 prov
= (TypeDescriptionProvider
)Activator
.CreateInstance(providerType
);
486 CodeAccessPermission
.RevertAssert();
489 Trace("Providers : Default provider found : {0}", providerType
.Name
);
490 AddProvider(prov
, type
);
491 providerAdded
= true;
495 // If we did not add a provider, check the base class.
496 if (!providerAdded
) {
497 Type baseType
= type
.BaseType
;
498 if (baseType
!= null && baseType
!= type
) {
499 CheckDefaultProvider(baseType
);
505 /// The CreateAssocation method creates an association between two objects.
506 /// Once an association is created, a designer or other filtering mechanism
507 /// can add properties that route to either object into the primary object's
508 /// property set. When a property invocation is made against the primary
509 /// object, GetAssocation will be called to resolve the actual object
510 /// instance that is related to its type parameter.
512 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
513 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
514 public static void CreateAssociation(object primary
, object secondary
)
518 throw new ArgumentNullException("primary");
521 if (secondary
== null)
523 throw new ArgumentNullException("secondary");
526 if (primary
== secondary
)
528 throw new ArgumentException(SR
.GetString(SR
.TypeDescriptorSameAssociation
));
531 if (_associationTable
== null)
533 lock (_internalSyncObject
)
535 if (_associationTable
== null)
537 _associationTable
= new WeakHashtable();
542 IList associations
= (IList
)_associationTable
[primary
];
544 if (associations
== null)
546 lock (_associationTable
)
548 associations
= (IList
)_associationTable
[primary
];
549 if (associations
== null)
551 associations
= new ArrayList(4);
552 _associationTable
.SetWeak(primary
, associations
);
558 for (int idx
= associations
.Count
- 1; idx
>= 0; idx
--)
560 WeakReference r
= (WeakReference
)associations
[idx
];
561 if (r
.IsAlive
&& r
.Target
== secondary
)
563 throw new ArgumentException(SR
.GetString(SR
.TypeDescriptorAlreadyAssociated
));
570 associations
.Add(new WeakReference(secondary
));
575 /// Creates an instance of the designer associated with the
576 /// specified component.
578 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Security", "CA2113:SecureLateBindingMethods")]
579 public static IDesigner
CreateDesigner(IComponent component
, Type designerBaseType
)
581 Type designerType
= null;
582 IDesigner designer
= null;
584 // Get the set of attributes for this type
586 AttributeCollection attributes
= GetAttributes(component
);
588 for (int i
= 0; i
< attributes
.Count
; i
++)
590 DesignerAttribute da
= attributes
[i
] as DesignerAttribute
;
593 Type attributeBaseType
= Type
.GetType(da
.DesignerBaseTypeName
);
594 if (attributeBaseType
!= null && attributeBaseType
== designerBaseType
)
596 ISite site
= component
.Site
;
597 bool foundService
= false;
601 ITypeResolutionService tr
= (ITypeResolutionService
)site
.GetService(typeof(ITypeResolutionService
));
605 designerType
= tr
.GetType(da
.DesignerTypeName
);
611 designerType
= Type
.GetType(da
.DesignerTypeName
);
614 Debug
.Assert(designerType
!= null, "It may be okay for the designer not to load, but we failed to load designer for component of type '" + component
.GetType().FullName
+ "' because designer of type '" + da
.DesignerTypeName
+ "'");
615 if (designerType
!= null)
623 if (designerType
!= null)
625 designer
= (IDesigner
)SecurityUtils
.SecureCreateInstance(designerType
, null, true);
632 /// This dynamically binds an EventDescriptor to a type.
634 [ReflectionPermission(SecurityAction
.LinkDemand
, Flags
=ReflectionPermissionFlag
.MemberAccess
)]
635 public static EventDescriptor
CreateEvent(Type componentType
, string name
, Type type
, params Attribute
[] attributes
)
637 return new ReflectEventDescriptor(componentType
, name
, type
, attributes
);
641 /// This creates a new event descriptor identical to an existing event descriptor. The new event descriptor
642 /// has the specified metadata attributes merged with the existing metadata attributes.
644 [ReflectionPermission(SecurityAction
.LinkDemand
, Flags
=ReflectionPermissionFlag
.MemberAccess
)]
645 public static EventDescriptor
CreateEvent(Type componentType
, EventDescriptor oldEventDescriptor
, params Attribute
[] attributes
)
647 return new ReflectEventDescriptor(componentType
, oldEventDescriptor
, attributes
);
651 /// This method will search internal tables within TypeDescriptor for
652 /// a TypeDescriptionProvider object that is associated with the given
653 /// data type. If it finds one, it will delegate the call to that object.
655 public static object CreateInstance(IServiceProvider provider
, Type objectType
, Type
[] argTypes
, object[] args
)
657 if (objectType
== null)
659 throw new ArgumentNullException("objectType");
662 if (argTypes
!= null)
666 throw new ArgumentNullException("args");
669 if (argTypes
.Length
!= args
.Length
)
671 throw new ArgumentException(SR
.GetString(SR
.TypeDescriptorArgsCountMismatch
));
675 object instance
= null;
677 // See if the provider wants to offer a TypeDescriptionProvider to delegate to. This allows
678 // a caller to have complete control over all object instantiation.
679 if (provider
!= null) {
680 TypeDescriptionProvider p
= provider
.GetService(typeof(TypeDescriptionProvider
)) as TypeDescriptionProvider
;
682 instance
= p
.CreateInstance(provider
, objectType
, argTypes
, args
);
686 if (instance
== null) {
687 instance
= NodeFor(objectType
).CreateInstance(provider
, objectType
, argTypes
, args
);
694 /// This dynamically binds a PropertyDescriptor to a type.
696 [ReflectionPermission(SecurityAction
.LinkDemand
, Flags
=ReflectionPermissionFlag
.MemberAccess
)]
697 public static PropertyDescriptor
CreateProperty(Type componentType
, string name
, Type type
, params Attribute
[] attributes
)
699 return new ReflectPropertyDescriptor(componentType
, name
, type
, attributes
);
703 /// This creates a new property descriptor identical to an existing property descriptor. The new property descriptor
704 /// has the specified metadata attributes merged with the existing metadata attributes.
706 [ReflectionPermission(SecurityAction
.LinkDemand
, Flags
=ReflectionPermissionFlag
.MemberAccess
)]
707 public static PropertyDescriptor
CreateProperty(Type componentType
, PropertyDescriptor oldPropertyDescriptor
, params Attribute
[] attributes
)
710 // We must do some special case work here for extended properties. If the old property descriptor is really
711 // an extender property that is being surfaced on a component as a normal property, then we must
712 // do work here or else ReflectPropertyDescriptor will fail to resolve the get and set methods. We check
713 // for the necessary ExtenderProvidedPropertyAttribute and if we find it, we create an
714 // ExtendedPropertyDescriptor instead. We only do this if the component class is the same, since the user
715 // may want to re-route the property to a different target.
717 if (componentType
== oldPropertyDescriptor
.ComponentType
)
719 ExtenderProvidedPropertyAttribute attr
= (ExtenderProvidedPropertyAttribute
)
720 oldPropertyDescriptor
.Attributes
[
721 typeof(ExtenderProvidedPropertyAttribute
)];
723 ReflectPropertyDescriptor reflectDesc
= attr
.ExtenderProperty
as ReflectPropertyDescriptor
;
724 if (reflectDesc
!= null)
726 return new ExtendedPropertyDescriptor(oldPropertyDescriptor
, attributes
);
731 DebugReflectPropertyDescriptor debugReflectDesc
= attr
.ExtenderProperty
as DebugReflectPropertyDescriptor
;
732 if (debugReflectDesc
!= null)
734 return new DebugExtendedPropertyDescriptor(oldPropertyDescriptor
, attributes
);
740 // This is either a normal prop or the caller has changed target classes.
742 return new ReflectPropertyDescriptor(componentType
, oldPropertyDescriptor
, attributes
);
746 /// Debug code that runs the output of a TypeDescriptor query into a debug
747 /// type descriptor that uses the V1.0 algorithm. This code will assert
748 /// if the two type descriptors do not agree. This method returns true if
749 /// validation should be performed for the type.
752 private static bool DebugShouldValidate(object key
)
754 // Check our switch first.
756 if (EnableValidation
.Enabled
)
760 // We only validate if there are no custom providers all the way
761 // up the class chain.
762 TypeDescriptionNode node
= _providerTable
[key
] as TypeDescriptionNode
;
763 if (node
!= null && !(node
.Provider
is ReflectTypeDescriptionProvider
))
770 key
= GetNodeForBaseType((Type
)key
);
775 if (((Type
)key
).IsCOMObject
)
788 /// Debug code that runs the output of a TypeDescriptor query into a debug
789 /// type descriptor that uses the V1.0 algorithm. This code will assert
790 /// if the two type descriptors do not agree.
792 [Conditional("DEBUG")]
793 private static void DebugValidate(Type type
, AttributeCollection attributes
, AttributeCollection debugAttributes
)
796 if (!DebugShouldValidate(type
)) return;
797 DebugValidate(attributes
, debugAttributes
);
802 /// Debug code that runs the output of a TypeDescriptor query into a debug
803 /// type descriptor that uses the V1.0 algorithm. This code will assert
804 /// if the two type descriptors do not agree.
806 [Conditional("DEBUG")]
807 private static void DebugValidate(AttributeCollection attributes
, AttributeCollection debugAttributes
)
811 if (attributes
.Count
>= debugAttributes
.Count
)
813 foreach(Attribute a
in attributes
)
815 if (!(a
is GuidAttribute
) && !(a
is ComVisibleAttribute
))
818 bool typeFound
= false;
820 // Many attributes don't implement .Equals correctly,
821 // so they will fail an equality check. But we want to
822 // make sure that common ones like Browsable and ReadOnly
823 // were correctly picked up. So only check the ones in
825 if (!a
.GetType().FullName
.StartsWith("System.Component"))
833 foreach(Attribute b
in debugAttributes
)
835 if (!typeFound
&& a
.GetType() == b
.GetType())
840 // Semitrust may throw here.
857 if (!found
&& !a
.IsDefaultAttribute())
861 Debug
.Fail(string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Attribute {0} was found but failed equality. Perhaps attribute .Equals is not implemented correctly?", a
.GetType().Name
));
865 Debug
.Fail(string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Attribute {0} should not exist", a
.GetType().Name
));
873 foreach(Attribute b
in debugAttributes
)
875 // We skip all interop attributes because interface merging has changed on purpose.
876 if (!(b
is GuidAttribute
) && !(b
is ComVisibleAttribute
) && !(b
is InterfaceTypeAttribute
) && !(b
is ReadOnlyAttribute
))
879 bool typeFound
= false;
881 // Many attributes don't implement .Equals correctly,
882 // so they will fail an equality check. But we want to
883 // make sure that common ones like Browsable and ReadOnly
884 // were correctly picked up. So only check the ones in
886 if (!b
.GetType().FullName
.StartsWith("System.Component"))
894 foreach(Attribute a
in attributes
)
896 if (!typeFound
&& a
.GetType() == b
.GetType())
901 // Semitrust may throw here.
918 if (!found
&& !b
.IsDefaultAttribute())
922 Debug
.Fail(string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Attribute {0} should exist", b
.GetType().Name
));
932 /// Debug code that runs the output of a TypeDescriptor query into a debug
933 /// type descriptor that uses the V1.0 algorithm. This code will assert
934 /// if the two type descriptors do not agree.
936 [Conditional("DEBUG")]
937 private static void DebugValidate(AttributeCollection attributes
, Type type
)
940 if (!DebugShouldValidate(type
)) return;
941 AttributeCollection debugAttributes
= DebugTypeDescriptor
.GetAttributes(type
);
942 DebugValidate(attributes
, debugAttributes
);
947 /// Debug code that runs the output of a TypeDescriptor query into a debug
948 /// type descriptor that uses the V1.0 algorithm. This code will assert
949 /// if the two type descriptors do not agree.
951 [Conditional("DEBUG")]
952 private static void DebugValidate(AttributeCollection attributes
, object instance
, bool noCustomTypeDesc
)
955 if (!DebugShouldValidate(instance
)) return;
956 AttributeCollection debugAttributes
= DebugTypeDescriptor
.GetAttributes(instance
, noCustomTypeDesc
);
957 DebugValidate(attributes
, debugAttributes
);
962 /// Debug code that runs the output of a TypeDescriptor query into a debug
963 /// type descriptor that uses the V1.0 algorithm. This code will assert
964 /// if the two type descriptors do not agree.
966 [Conditional("DEBUG")]
967 private static void DebugValidate(TypeConverter converter
, Type type
)
970 if (!DebugShouldValidate(type
)) return;
971 TypeConverter debugConverter
= DebugTypeDescriptor
.GetConverter(type
);
972 Debug
.Assert(debugConverter
.GetType() == converter
.GetType(), "TypeDescriptor engine Validation Failure.");
977 /// Debug code that runs the output of a TypeDescriptor query into a debug
978 /// type descriptor that uses the V1.0 algorithm. This code will assert
979 /// if the two type descriptors do not agree.
981 [Conditional("DEBUG")]
982 private static void DebugValidate(TypeConverter converter
, object instance
, bool noCustomTypeDesc
)
985 if (!DebugShouldValidate(instance
)) return;
986 TypeConverter debugConverter
= DebugTypeDescriptor
.GetConverter(instance
, noCustomTypeDesc
);
987 Debug
.Assert(debugConverter
.GetType() == converter
.GetType(), "TypeDescriptor engine Validation Failure.");
992 /// Debug code that runs the output of a TypeDescriptor query into a debug
993 /// type descriptor that uses the V1.0 algorithm. This code will assert
994 /// if the two type descriptors do not agree.
996 [Conditional("DEBUG")]
997 private static void DebugValidate(EventDescriptorCollection events
, Type type
, Attribute
[] attributes
)
1000 if (!DebugShouldValidate(type
)) return;
1001 EventDescriptorCollection debugEvents
= DebugTypeDescriptor
.GetEvents(type
, attributes
);
1002 Debug
.Assert(debugEvents
.Count
== events
.Count
, "TypeDescriptor engine Validation Failure. Event counts differ.");
1003 foreach(EventDescriptor debugEvt
in debugEvents
)
1005 EventDescriptor evt
= null;
1007 foreach(EventDescriptor realEvt
in events
)
1009 if (realEvt
.Name
.Equals(debugEvt
.Name
) && realEvt
.EventType
== debugEvt
.EventType
&& realEvt
.ComponentType
== debugEvt
.ComponentType
)
1016 Debug
.Assert(evt
!= null, "TypeDescriptor engine Validation Failure. Event " + debugEvt
.Name
+ " does not exist or is of the wrong type.");
1019 AttributeCollection attrs
= evt
.Attributes
;
1020 if (attrs
[typeof(AttributeProviderAttribute
)] == null)
1022 AttributeCollection debugAttrs
= debugEvt
.Attributes
;
1023 DebugValidate(evt
.EventType
, attrs
, debugAttrs
);
1031 /// Debug code that runs the output of a TypeDescriptor query into a debug
1032 /// type descriptor that uses the V1.0 algorithm. This code will assert
1033 /// if the two type descriptors do not agree.
1035 [Conditional("DEBUG")]
1036 private static void DebugValidate(EventDescriptorCollection events
, object instance
, Attribute
[] attributes
, bool noCustomTypeDesc
)
1039 if (!DebugShouldValidate(instance
)) return;
1040 EventDescriptorCollection debugEvents
= DebugTypeDescriptor
.GetEvents(instance
, attributes
, noCustomTypeDesc
);
1041 Debug
.Assert(debugEvents
.Count
== events
.Count
, "TypeDescriptor engine Validation Failure. Event counts differ.");
1042 foreach(EventDescriptor debugEvt
in debugEvents
)
1044 EventDescriptor evt
= null;
1046 foreach(EventDescriptor realEvt
in events
)
1048 if (realEvt
.Name
.Equals(debugEvt
.Name
) && realEvt
.EventType
== debugEvt
.EventType
&& realEvt
.ComponentType
== debugEvt
.ComponentType
)
1055 Debug
.Assert(evt
!= null, "TypeDescriptor engine Validation Failure. Event " + debugEvt
.Name
+ " does not exist or is of the wrong type.");
1058 AttributeCollection attrs
= evt
.Attributes
;
1059 if (attrs
[typeof(AttributeProviderAttribute
)] == null)
1061 AttributeCollection debugAttrs
= debugEvt
.Attributes
;
1062 DebugValidate(evt
.EventType
, attrs
, debugAttrs
);
1070 /// Debug code that runs the output of a TypeDescriptor query into a debug
1071 /// type descriptor that uses the V1.0 algorithm. This code will assert
1072 /// if the two type descriptors do not agree.
1074 [Conditional("DEBUG")]
1075 private static void DebugValidate(PropertyDescriptorCollection properties
, Type type
, Attribute
[] attributes
)
1078 if (!DebugShouldValidate(type
)) return;
1079 PropertyDescriptorCollection debugProperties
= DebugTypeDescriptor
.GetProperties(type
, attributes
);
1081 if (debugProperties
.Count
> properties
.Count
)
1083 foreach(PropertyDescriptor debugProp
in debugProperties
)
1085 PropertyDescriptor prop
= null;
1087 foreach(PropertyDescriptor realProp
in properties
)
1089 if (realProp
.Name
.Equals(debugProp
.Name
) && realProp
.PropertyType
== debugProp
.PropertyType
&& realProp
.ComponentType
== debugProp
.ComponentType
)
1098 Debug
.Fail(string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Property {0} of type {1} should exist.", debugProp
.Name
, debugProp
.GetType().Name
));
1102 else if (properties
.Count
> debugProperties
.Count
)
1104 foreach(PropertyDescriptor prop
in properties
)
1106 PropertyDescriptor debugProp
= null;
1108 foreach(PropertyDescriptor realProp
in debugProperties
)
1110 if (realProp
.Name
.Equals(prop
.Name
) && realProp
.PropertyType
== prop
.PropertyType
&& realProp
.ComponentType
== prop
.ComponentType
)
1112 debugProp
= realProp
;
1117 if (debugProp
== null)
1119 Debug
.Fail(string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Property {0} of type {1} should not exist.", prop
.Name
, prop
.GetType().Name
));
1125 foreach(PropertyDescriptor debugProp
in debugProperties
)
1127 PropertyDescriptor prop
= null;
1129 foreach(PropertyDescriptor realProp
in properties
)
1131 if (realProp
.Name
.Equals(debugProp
.Name
) && realProp
.PropertyType
== debugProp
.PropertyType
&& realProp
.ComponentType
== debugProp
.ComponentType
)
1138 Debug
.Assert(prop
!= null, string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Property {0} of type {1} exists but perhaps type mismatched?", debugProp
.Name
, debugProp
.GetType().Name
));
1141 AttributeCollection attrs
= prop
.Attributes
;
1142 if (attrs
[typeof(AttributeProviderAttribute
)] == null)
1144 AttributeCollection debugAttrs
= debugProp
.Attributes
;
1145 DebugValidate(prop
.PropertyType
, attrs
, debugAttrs
);
1154 /// Debug code that runs the output of a TypeDescriptor query into a debug
1155 /// type descriptor that uses the V1.0 algorithm. This code will assert
1156 /// if the two type descriptors do not agree.
1158 [Conditional("DEBUG")]
1159 private static void DebugValidate(PropertyDescriptorCollection properties
, object instance
, Attribute
[] attributes
, bool noCustomTypeDesc
)
1162 if (!DebugShouldValidate(instance
)) return;
1163 PropertyDescriptorCollection debugProperties
= DebugTypeDescriptor
.GetProperties(instance
, attributes
, noCustomTypeDesc
);
1165 if (debugProperties
.Count
> properties
.Count
)
1167 foreach(PropertyDescriptor debugProp
in debugProperties
)
1169 PropertyDescriptor prop
= null;
1171 foreach(PropertyDescriptor realProp
in properties
)
1173 if (realProp
.Name
.Equals(debugProp
.Name
) && realProp
.PropertyType
== debugProp
.PropertyType
&& realProp
.ComponentType
== debugProp
.ComponentType
)
1182 Debug
.Fail(string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Property {0} of type {1} should exist.", debugProp
.Name
, debugProp
.GetType().Name
));
1186 else if (properties
.Count
> debugProperties
.Count
)
1188 foreach(PropertyDescriptor prop
in properties
)
1190 PropertyDescriptor debugProp
= null;
1192 foreach(PropertyDescriptor realProp
in debugProperties
)
1194 if (realProp
.Name
.Equals(prop
.Name
) && realProp
.PropertyType
== prop
.PropertyType
&& realProp
.ComponentType
== prop
.ComponentType
)
1196 debugProp
= realProp
;
1201 if (debugProp
== null)
1203 Debug
.Fail(string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Property {0} of type {1} should not exist.", prop
.Name
, prop
.GetType().Name
));
1209 foreach(PropertyDescriptor debugProp
in debugProperties
)
1211 PropertyDescriptor prop
= null;
1213 foreach(PropertyDescriptor realProp
in properties
)
1215 if (realProp
.Name
.Equals(debugProp
.Name
) && realProp
.PropertyType
== debugProp
.PropertyType
&& realProp
.ComponentType
== debugProp
.ComponentType
)
1222 Debug
.Assert(prop
!= null, string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor engine Validation Failure. Property {0} of type {1} exists but perhaps type mismatched?", debugProp
.Name
, debugProp
.GetType().Name
));
1225 AttributeCollection attrs
= prop
.Attributes
;
1226 if (attrs
[typeof(AttributeProviderAttribute
)] == null)
1228 AttributeCollection debugAttrs
= debugProp
.Attributes
;
1229 DebugValidate(prop
.PropertyType
, attrs
, debugAttrs
);
1238 /// This API is used to remove any members from the given
1239 /// collection that do not match the attribute array. If members
1240 /// need to be removed, a new ArrayList wil be created that
1241 /// contains only the remaining members. The API returns
1242 /// NULL if it did not need to filter any members.
1244 private static ArrayList
FilterMembers(IList members
, Attribute
[] attributes
) {
1245 ArrayList newMembers
= null;
1246 int memberCount
= members
.Count
;
1248 for (int idx
= 0; idx
< memberCount
; idx
++) {
1252 for (int attrIdx
= 0; attrIdx
< attributes
.Length
; attrIdx
++) {
1253 if (ShouldHideMember((MemberDescriptor
)members
[idx
], attributes
[attrIdx
])) {
1260 // We have to hide. If this is the first time, we need to init
1261 // newMembers to have all the valid members we have previously
1263 if (newMembers
== null) {
1264 newMembers
= new ArrayList(memberCount
);
1265 for (int validIdx
= 0; validIdx
< idx
; validIdx
++) {
1266 newMembers
.Add(members
[validIdx
]);
1270 else if (newMembers
!= null) {
1271 newMembers
.Add(members
[idx
]);
1280 /// The GetAssociation method returns the correct object to invoke
1281 /// for the requested type. It never returns null.
1283 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1284 public static object GetAssociation(Type type
, object primary
)
1288 throw new ArgumentNullException("type");
1291 if (primary
== null)
1293 throw new ArgumentNullException("primary");
1296 object associatedObject
= primary
;
1298 if (!type
.IsInstanceOfType(primary
))
1300 // Check our association table for a match.
1302 Hashtable assocTable
= _associationTable
;
1303 if (assocTable
!= null)
1305 IList associations
= (IList
)assocTable
[primary
];
1306 if (associations
!= null)
1310 for (int idx
= associations
.Count
- 1; idx
>= 0; idx
--)
1312 // Look for an associated object that has a type that
1313 // matches the given type.
1315 WeakReference weakRef
= (WeakReference
)associations
[idx
];
1316 object secondary
= weakRef
.Target
;
1317 if (secondary
== null)
1319 Trace("Associations : Removing dead reference in assocation table");
1320 associations
.RemoveAt(idx
);
1322 else if (type
.IsInstanceOfType(secondary
))
1324 Trace("Associations : Associated {0} to {1}", primary
.GetType().Name
, secondary
.GetType().Name
);
1325 associatedObject
= secondary
;
1332 // Not in our table. We have a default association with a designer
1333 // if that designer is a component.
1335 if (associatedObject
== primary
)
1337 IComponent component
= primary
as IComponent
;
1338 if (component
!= null)
1340 ISite site
= component
.Site
;
1342 if (site
!= null && site
.DesignMode
)
1344 IDesignerHost host
= site
.GetService(typeof(IDesignerHost
)) as IDesignerHost
;
1347 object designer
= host
.GetDesigner(component
);
1349 // We only use the designer if it has a compatible class. If we
1350 // got here, we're probably hosed because the user just passed in
1351 // an object that this PropertyDescriptor can't munch on, but it's
1352 // clearer to use that object instance instead of it's designer.
1354 if (designer
!= null && type
.IsInstanceOfType(designer
))
1356 Trace("Associations : Associated {0} to {1}", primary
.GetType().Name
, designer
.GetType().Name
);
1357 associatedObject
= designer
;
1365 return associatedObject
;
1369 /// Gets a collection of attributes for the specified type of component.
1371 public static AttributeCollection
GetAttributes(Type componentType
)
1373 if (componentType
== null)
1375 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
1376 return new AttributeCollection((Attribute
[])null);
1379 AttributeCollection attributes
= GetDescriptor(componentType
, "componentType").GetAttributes();
1380 DebugValidate(attributes
, componentType
);
1385 /// Gets a collection of attributes for the specified component.
1387 public static AttributeCollection
GetAttributes(object component
)
1389 return GetAttributes(component
, false);
1393 /// Gets a collection of attributes for the specified component.
1395 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1396 public static AttributeCollection
GetAttributes(object component
, bool noCustomTypeDesc
)
1398 if (component
== null)
1400 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
1401 return new AttributeCollection((Attribute
[])null);
1404 // We create a sort of pipeline for mucking with metadata. The pipeline
1405 // goes through the following process:
1407 // 1. Merge metadata from extenders.
1408 // 2. Allow services to filter the metadata
1409 // 3. If an attribute filter was specified, apply that.
1411 // The goal here is speed. We get speed by not copying or
1412 // allocating memory. We do this by allowing each phase of the
1413 // pipeline to cache its data in the object cache. If
1414 // a phase makes a change to the results, this change must cause
1415 // successive phases to recompute their results as well. "Results" is
1416 // always a collection, and the various stages of the pipeline may
1417 // replace or modify this collection (depending on if it's a
1418 // read-only IList or not). It is possible for the orignal
1419 // descriptor or attribute collection to pass through the entire
1420 // pipeline without modification.
1422 ICustomTypeDescriptor typeDesc
= GetDescriptor(component
, noCustomTypeDesc
);
1423 ICollection results
= typeDesc
.GetAttributes();
1425 // If we are handed a custom type descriptor we have several choices of action
1426 // we can take. If noCustomTypeDesc is true, it means that the custom type
1427 // descriptor is trying to find a baseline set of properties. In this case
1428 // we should merge in extended properties, but we do not let designers filter
1429 // because we're not done with the property set yet. If noCustomTypeDesc
1430 // is false, we don't do extender properties because the custom type descriptor
1431 // has already added them. In this case, we are doing a final pass so we
1432 // want to apply filtering. Finally, if the incoming object is not a custom
1433 // type descriptor, we do extenders and the filter.
1435 if (component
is ICustomTypeDescriptor
)
1437 if (noCustomTypeDesc
)
1439 ICustomTypeDescriptor extDesc
= GetExtendedDescriptor(component
);
1440 if (extDesc
!= null)
1442 ICollection extResults
= extDesc
.GetAttributes();
1443 results
= PipelineMerge(PIPELINE_ATTRIBUTES
, results
, extResults
, component
, null);
1448 results
= PipelineFilter(PIPELINE_ATTRIBUTES
, results
, component
, null);
1453 IDictionary cache
= GetCache(component
);
1455 results
= PipelineInitialize(PIPELINE_ATTRIBUTES
, results
, cache
);
1457 ICustomTypeDescriptor extDesc
= GetExtendedDescriptor(component
);
1458 if (extDesc
!= null)
1460 ICollection extResults
= extDesc
.GetAttributes();
1461 results
= PipelineMerge(PIPELINE_ATTRIBUTES
, results
, extResults
, component
, cache
);
1464 results
= PipelineFilter(PIPELINE_ATTRIBUTES
, results
, component
, cache
);
1467 AttributeCollection attrs
= results
as AttributeCollection
;
1470 Trace("Attributes : Allocated new attribute collection for {0}", component
.GetType().Name
);
1471 Attribute
[] attrArray
= new Attribute
[results
.Count
];
1472 results
.CopyTo(attrArray
, 0);
1473 attrs
= new AttributeCollection(attrArray
);
1476 DebugValidate(attrs
, component
, noCustomTypeDesc
);
1481 /// Helper function to obtain a cache for the given object.
1483 internal static IDictionary
GetCache(object instance
)
1485 return NodeFor(instance
).GetCache(instance
);
1489 /// Gets the name of the class for the specified component.
1491 public static string GetClassName(object component
)
1493 return GetClassName(component
, false);
1497 /// Gets the name of the class for the specified component.
1499 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1500 public static string GetClassName(object component
, bool noCustomTypeDesc
)
1502 return GetDescriptor(component
, noCustomTypeDesc
).GetClassName();
1506 /// Gets the name of the class for the specified type.
1508 public static string GetClassName(Type componentType
)
1510 return GetDescriptor(componentType
, "componentType").GetClassName();
1514 /// The name of the class for the specified component.
1516 public static string GetComponentName(object component
)
1518 return GetComponentName(component
, false);
1522 /// Gets the name of the class for the specified component.
1524 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1525 public static string GetComponentName(object component
, bool noCustomTypeDesc
)
1527 return GetDescriptor(component
, noCustomTypeDesc
).GetComponentName();
1531 /// Gets a type converter for the type of the specified component.
1533 public static TypeConverter
GetConverter(object component
)
1535 return GetConverter(component
, false);
1539 /// Gets a type converter for the type of the specified component.
1541 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1542 public static TypeConverter
GetConverter(object component
, bool noCustomTypeDesc
)
1544 TypeConverter converter
= GetDescriptor(component
, noCustomTypeDesc
).GetConverter();
1545 DebugValidate(converter
, component
, noCustomTypeDesc
);
1550 /// Gets a type converter for the specified type.
1552 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
1553 public static TypeConverter
GetConverter(Type type
)
1555 TypeConverter converter
= GetDescriptor(type
, "type").GetConverter();
1556 DebugValidate(converter
, type
);
1561 /// Gets the default event for the specified type of component.
1563 public static EventDescriptor
GetDefaultEvent(Type componentType
)
1565 if (componentType
== null)
1567 Debug
.Fail("COMPAT: Returning null, but you should not pass null here");
1571 return GetDescriptor(componentType
, "componentType").GetDefaultEvent();
1575 /// Gets the default event for the specified component.
1577 public static EventDescriptor
GetDefaultEvent(object component
)
1579 return GetDefaultEvent(component
, false);
1583 /// Gets the default event for a component.
1585 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1586 public static EventDescriptor
GetDefaultEvent(object component
, bool noCustomTypeDesc
)
1588 if (component
== null)
1590 Debug
.Fail("COMPAT: Returning null, but you should not pass null here");
1594 return GetDescriptor(component
, noCustomTypeDesc
).GetDefaultEvent();
1598 /// Gets the default property for the specified type of component.
1600 public static PropertyDescriptor
GetDefaultProperty(Type componentType
)
1602 if (componentType
== null)
1604 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
1608 return GetDescriptor(componentType
, "componentType").GetDefaultProperty();
1612 /// Gets the default property for the specified component.
1614 public static PropertyDescriptor
GetDefaultProperty(object component
)
1616 return GetDefaultProperty(component
, false);
1620 /// Gets the default property for the specified component.
1622 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1623 public static PropertyDescriptor
GetDefaultProperty(object component
, bool noCustomTypeDesc
)
1625 if (component
== null)
1627 Debug
.Fail("COMPAT: Returning null, but you should not pass null here");
1631 return GetDescriptor(component
, noCustomTypeDesc
).GetDefaultProperty();
1635 /// Returns a custom type descriptor for the given type.
1636 /// Performs arg checking so callers don't have to.
1638 internal static ICustomTypeDescriptor
GetDescriptor(Type type
, string typeName
)
1642 throw new ArgumentNullException(typeName
);
1645 return NodeFor(type
).GetTypeDescriptor(type
);
1649 /// Returns a custom type descriptor for the given instance.
1650 /// Performs arg checking so callers don't have to. This
1651 /// will call through to instance if it is a custom type
1654 internal static ICustomTypeDescriptor
GetDescriptor(object component
, bool noCustomTypeDesc
)
1656 if (component
== null)
1658 throw new ArgumentException("component");
1661 if (component
is IUnimplemented
) {
1662 throw new NotSupportedException(SR
.GetString(SR
.TypeDescriptorUnsupportedRemoteObject
, component
.GetType().FullName
));
1666 ICustomTypeDescriptor desc
= NodeFor(component
).GetTypeDescriptor(component
);
1667 ICustomTypeDescriptor d
= component
as ICustomTypeDescriptor
;
1668 if (!noCustomTypeDesc
&& d
!= null)
1670 desc
= new MergedTypeDescriptor(d
, desc
);
1677 /// Returns an extended custom type descriptor for the given instance.
1679 internal static ICustomTypeDescriptor
GetExtendedDescriptor(object component
)
1681 if (component
== null)
1683 throw new ArgumentException("component");
1686 return NodeFor(component
).GetExtendedTypeDescriptor(component
);
1690 /// Gets an editor with the specified base type for the
1691 /// specified component.
1693 public static object GetEditor(object component
, Type editorBaseType
)
1695 return GetEditor(component
, editorBaseType
, false);
1699 /// Gets an editor with the specified base type for the
1700 /// specified component.
1702 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1703 public static object GetEditor(object component
, Type editorBaseType
, bool noCustomTypeDesc
)
1705 if (editorBaseType
== null)
1707 throw new ArgumentNullException("editorBaseType");
1710 return GetDescriptor(component
, noCustomTypeDesc
).GetEditor(editorBaseType
);
1714 /// Gets an editor with the specified base type for the specified type.
1716 public static object GetEditor(Type type
, Type editorBaseType
)
1718 if (editorBaseType
== null)
1720 throw new ArgumentNullException("editorBaseType");
1723 return GetDescriptor(type
, "type").GetEditor(editorBaseType
);
1727 /// Gets a collection of events for a specified type of component.
1729 public static EventDescriptorCollection
GetEvents(Type componentType
)
1731 if (componentType
== null)
1733 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
1734 return new EventDescriptorCollection(null, true);
1737 return GetDescriptor(componentType
, "componentType").GetEvents();
1741 /// Gets a collection of events for a specified type of
1742 /// component using a specified array of attributes as a filter.
1744 public static EventDescriptorCollection
GetEvents(Type componentType
, Attribute
[] attributes
)
1746 if (componentType
== null)
1748 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
1749 return new EventDescriptorCollection(null, true);
1752 EventDescriptorCollection events
= GetDescriptor(componentType
, "componentType").GetEvents(attributes
);
1754 if (attributes
!= null && attributes
.Length
> 0) {
1755 ArrayList filteredEvents
= FilterMembers(events
, attributes
);
1756 if (filteredEvents
!= null) {
1757 events
= new EventDescriptorCollection((EventDescriptor
[])filteredEvents
.ToArray(typeof(EventDescriptor
)), true);
1761 DebugValidate(events
, componentType
, attributes
);
1766 /// Gets a collection of events for a specified component.
1768 public static EventDescriptorCollection
GetEvents(object component
)
1770 return GetEvents(component
, null, false);
1774 /// Gets a collection of events for a specified component.
1776 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1777 public static EventDescriptorCollection
GetEvents(object component
, bool noCustomTypeDesc
)
1779 return GetEvents(component
, null, noCustomTypeDesc
);
1783 /// Gets a collection of events for a specified component
1784 /// using a specified array of attributes as a filter.
1786 public static EventDescriptorCollection
GetEvents(object component
, Attribute
[] attributes
)
1788 return GetEvents(component
, attributes
, false);
1792 /// Gets a collection of events for a specified component
1793 /// using a specified array of attributes as a filter.
1795 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1796 public static EventDescriptorCollection
GetEvents(object component
, Attribute
[] attributes
, bool noCustomTypeDesc
)
1798 if (component
== null)
1800 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
1801 return new EventDescriptorCollection(null, true);
1804 // We create a sort of pipeline for mucking with metadata. The pipeline
1805 // goes through the following process:
1807 // 1. Merge metadata from extenders.
1808 // 2. Allow services to filter the metadata
1809 // 3. If an attribute filter was specified, apply that.
1811 // The goal here is speed. We get speed by not copying or
1812 // allocating memory. We do this by allowing each phase of the
1813 // pipeline to cache its data in the object cache. If
1814 // a phase makes a change to the results, this change must cause
1815 // successive phases to recompute their results as well. "Results" is
1816 // always a collection, and the various stages of the pipeline may
1817 // replace or modify this collection (depending on if it's a
1818 // read-only IList or not). It is possible for the orignal
1819 // descriptor or attribute collection to pass through the entire
1820 // pipeline without modification.
1822 ICustomTypeDescriptor typeDesc
= GetDescriptor(component
, noCustomTypeDesc
);
1823 ICollection results
;
1825 // If we are handed a custom type descriptor we have several choices of action
1826 // we can take. If noCustomTypeDesc is true, it means that the custom type
1827 // descriptor is trying to find a baseline set of events. In this case
1828 // we should merge in extended events, but we do not let designers filter
1829 // because we're not done with the event set yet. If noCustomTypeDesc
1830 // is false, we don't do extender events because the custom type descriptor
1831 // has already added them. In this case, we are doing a final pass so we
1832 // want to apply filtering. Finally, if the incoming object is not a custom
1833 // type descriptor, we do extenders and the filter.
1835 if (component
is ICustomTypeDescriptor
)
1837 results
= typeDesc
.GetEvents(attributes
);
1838 if (noCustomTypeDesc
)
1840 ICustomTypeDescriptor extDesc
= GetExtendedDescriptor(component
);
1841 if (extDesc
!= null)
1843 ICollection extResults
= extDesc
.GetEvents(attributes
);
1844 results
= PipelineMerge(PIPELINE_EVENTS
, results
, extResults
, component
, null);
1849 results
= PipelineFilter(PIPELINE_EVENTS
, results
, component
, null);
1850 results
= PipelineAttributeFilter(PIPELINE_EVENTS
, results
, attributes
, component
, null);
1855 IDictionary cache
= GetCache(component
);
1856 results
= typeDesc
.GetEvents(attributes
);
1857 results
= PipelineInitialize(PIPELINE_EVENTS
, results
, cache
);
1858 ICustomTypeDescriptor extDesc
= GetExtendedDescriptor(component
);
1859 if (extDesc
!= null)
1861 ICollection extResults
= extDesc
.GetEvents(attributes
);
1862 results
= PipelineMerge(PIPELINE_EVENTS
, results
, extResults
, component
, cache
);
1865 results
= PipelineFilter(PIPELINE_EVENTS
, results
, component
, cache
);
1866 results
= PipelineAttributeFilter(PIPELINE_EVENTS
, results
, attributes
, component
, cache
);
1869 EventDescriptorCollection evts
= results
as EventDescriptorCollection
;
1872 Trace("Events : Allocated new event collection for {0}", component
.GetType().Name
);
1873 EventDescriptor
[] eventArray
= new EventDescriptor
[results
.Count
];
1874 results
.CopyTo(eventArray
, 0);
1875 evts
= new EventDescriptorCollection(eventArray
, true);
1878 DebugValidate(evts
, component
, attributes
, noCustomTypeDesc
);
1884 /// This method is invoked during filtering when a name
1885 /// collision is encountered between two properties or events. This returns
1886 /// a suffix that can be appended to the name to make
1887 /// it unique. This will first attempt ot use the name of the
1888 /// extender. Failing that it will fall back to a static
1889 /// index that is continually incremented.
1891 private static string GetExtenderCollisionSuffix(MemberDescriptor member
)
1893 string suffix
= null;
1895 ExtenderProvidedPropertyAttribute exAttr
= member
.Attributes
[typeof(ExtenderProvidedPropertyAttribute
)] as ExtenderProvidedPropertyAttribute
;
1898 IExtenderProvider prov
= exAttr
.Provider
;
1903 IComponent component
= prov
as IComponent
;
1905 if (component
!= null && component
.Site
!= null)
1907 name
= component
.Site
.Name
;
1910 if (name
== null || name
.Length
== 0)
1912 int ci
= System
.Threading
.Interlocked
.Increment(ref _collisionIndex
) - 1;
1913 name
= ci
.ToString(CultureInfo
.InvariantCulture
);
1916 suffix
= string.Format(CultureInfo
.InvariantCulture
, "_{0}", name
);
1924 /// The name of the specified component, or null if the component has no name.
1925 /// In many cases this will return the same value as GetComponentName. If the
1926 /// component resides in a nested container or has other nested semantics, it may
1927 /// return a different fully qualfied name.
1929 public static string GetFullComponentName(object component
) {
1930 if (component
== null) throw new ArgumentNullException("component");
1931 return GetProvider(component
).GetFullComponentName(component
);
1934 private static Type
GetNodeForBaseType(Type searchType
)
1936 if (searchType
.IsInterface
)
1938 return InterfaceType
;
1940 else if (searchType
== InterfaceType
)
1944 return searchType
.BaseType
;
1948 /// Gets a collection of properties for a specified type of component.
1950 public static PropertyDescriptorCollection
GetProperties(Type componentType
)
1952 if (componentType
== null)
1954 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
1955 return new PropertyDescriptorCollection(null, true);
1958 return GetDescriptor(componentType
, "componentType").GetProperties();
1962 /// Gets a collection of properties for a specified type of
1963 /// component using a specified array of attributes as a filter.
1965 public static PropertyDescriptorCollection
GetProperties(Type componentType
, Attribute
[] attributes
)
1967 if (componentType
== null)
1969 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
1970 return new PropertyDescriptorCollection(null, true);
1973 PropertyDescriptorCollection properties
= GetDescriptor(componentType
, "componentType").GetProperties(attributes
);
1975 if (attributes
!= null && attributes
.Length
> 0) {
1976 ArrayList filteredProperties
= FilterMembers(properties
, attributes
);
1977 if (filteredProperties
!= null) {
1978 properties
= new PropertyDescriptorCollection((PropertyDescriptor
[])filteredProperties
.ToArray(typeof(PropertyDescriptor
)), true);
1982 DebugValidate(properties
, componentType
, attributes
);
1987 /// Gets a collection of properties for a specified component.
1989 public static PropertyDescriptorCollection
GetProperties(object component
)
1991 return GetProperties(component
, false);
1995 /// Gets a collection of properties for a specified component.
1997 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1998 public static PropertyDescriptorCollection
GetProperties(object component
, bool noCustomTypeDesc
)
2000 return GetPropertiesImpl(component
, null, noCustomTypeDesc
, true);
2004 /// Gets a collection of properties for a specified
2005 /// component using a specified array of attributes
2008 public static PropertyDescriptorCollection
GetProperties(object component
, Attribute
[] attributes
)
2010 return GetProperties(component
, attributes
, false);
2014 /// <para>Gets a collection of properties for a specified
2015 /// component using a specified array of attributes
2016 /// as a filter.</para>
2018 public static PropertyDescriptorCollection
GetProperties(object component
, Attribute
[] attributes
, bool noCustomTypeDesc
) {
2019 return GetPropertiesImpl(component
, attributes
, noCustomTypeDesc
, false);
2023 /// Gets a collection of properties for a specified component. Uses the attribute filter
2024 /// only if noAttributes is false. This is to preserve backward compat for the case when
2025 /// no attribute filter was passed in (as against passing in null).
2027 private static PropertyDescriptorCollection
GetPropertiesImpl(object component
, Attribute
[] attributes
, bool noCustomTypeDesc
, bool noAttributes
) {
2028 if (component
== null)
2030 Debug
.Fail("COMPAT: Returning an empty collection, but you should not pass null here");
2031 return new PropertyDescriptorCollection(null, true);
2034 // We create a sort of pipeline for mucking with metadata. The pipeline
2035 // goes through the following process:
2037 // 1. Merge metadata from extenders.
2038 // 2. Allow services to filter the metadata
2039 // 3. If an attribute filter was specified, apply that.
2041 // The goal here is speed. We get speed by not copying or
2042 // allocating memory. We do this by allowing each phase of the
2043 // pipeline to cache its data in the object cache. If
2044 // a phase makes a change to the results, this change must cause
2045 // successive phases to recompute their results as well. "Results" is
2046 // always a collection, and the various stages of the pipeline may
2047 // replace or modify this collection (depending on if it's a
2048 // read-only IList or not). It is possible for the orignal
2049 // descriptor or attribute collection to pass through the entire
2050 // pipeline without modification.
2052 ICustomTypeDescriptor typeDesc
= GetDescriptor(component
, noCustomTypeDesc
);
2053 ICollection results
;
2055 // If we are handed a custom type descriptor we have several choices of action
2056 // we can take. If noCustomTypeDesc is true, it means that the custom type
2057 // descriptor is trying to find a baseline set of properties. In this case
2058 // we should merge in extended properties, but we do not let designers filter
2059 // because we're not done with the property set yet. If noCustomTypeDesc
2060 // is false, we don't do extender properties because the custom type descriptor
2061 // has already added them. In this case, we are doing a final pass so we
2062 // want to apply filtering. Finally, if the incoming object is not a custom
2063 // type descriptor, we do extenders and the filter.
2065 if (component
is ICustomTypeDescriptor
)
2067 results
= noAttributes
? typeDesc
.GetProperties() : typeDesc
.GetProperties(attributes
);
2068 if (noCustomTypeDesc
)
2070 ICustomTypeDescriptor extDesc
= GetExtendedDescriptor(component
);
2071 if (extDesc
!= null)
2073 ICollection extResults
= noAttributes
? extDesc
.GetProperties() : extDesc
.GetProperties(attributes
);
2074 results
= PipelineMerge(PIPELINE_PROPERTIES
, results
, extResults
, component
, null);
2079 results
= PipelineFilter(PIPELINE_PROPERTIES
, results
, component
, null);
2080 results
= PipelineAttributeFilter(PIPELINE_PROPERTIES
, results
, attributes
, component
, null);
2085 IDictionary cache
= GetCache(component
);
2086 results
= noAttributes
? typeDesc
.GetProperties() : typeDesc
.GetProperties(attributes
);
2087 results
= PipelineInitialize(PIPELINE_PROPERTIES
, results
, cache
);
2088 ICustomTypeDescriptor extDesc
= GetExtendedDescriptor(component
);
2089 if (extDesc
!= null)
2091 ICollection extResults
= noAttributes
? extDesc
.GetProperties() : extDesc
.GetProperties(attributes
);
2092 results
= PipelineMerge(PIPELINE_PROPERTIES
, results
, extResults
, component
, cache
);
2095 results
= PipelineFilter(PIPELINE_PROPERTIES
, results
, component
, cache
);
2096 results
= PipelineAttributeFilter(PIPELINE_PROPERTIES
, results
, attributes
, component
, cache
);
2099 PropertyDescriptorCollection props
= results
as PropertyDescriptorCollection
;
2102 Trace("Properties : Allocated new property collection for {0}", component
.GetType().Name
);
2103 PropertyDescriptor
[] propArray
= new PropertyDescriptor
[results
.Count
];
2104 results
.CopyTo(propArray
, 0);
2105 props
= new PropertyDescriptorCollection(propArray
, true);
2108 DebugValidate(props
, component
, attributes
, noCustomTypeDesc
);
2114 /// The GetProvider method returns a type description provider for
2115 /// the given object or type. This will always return a type description
2116 /// provider. Even the default TypeDescriptor implementation is built on
2117 /// a TypeDescriptionProvider, and this will be returned unless there is
2118 /// another provider that someone else has added.
2120 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
2121 public static TypeDescriptionProvider
GetProvider(Type type
)
2125 throw new ArgumentNullException("type");
2128 return NodeFor(type
, true);
2132 /// The GetProvider method returns a type description provider for
2133 /// the given object or type. This will always return a type description
2134 /// provider. Even the default TypeDescriptor implementation is built on
2135 /// a TypeDescriptionProvider, and this will be returned unless there is
2136 /// another provider that someone else has added.
2138 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
2139 public static TypeDescriptionProvider
GetProvider(object instance
)
2141 if (instance
== null)
2143 throw new ArgumentNullException("instance");
2146 return NodeFor(instance
, true);
2150 /// This method returns a type description provider, but instead of creating
2151 /// a delegating provider for the type, this will walk all base types until
2152 /// it locates a provider. The provider returned cannot be cached. This
2153 /// method is used by the DelegatingTypeDescriptionProvider to efficiently
2154 /// locate the provider to delegate to.
2156 internal static TypeDescriptionProvider
GetProviderRecursive(Type type
) {
2157 return NodeFor(type
, false);
2161 /// Returns an Type instance that can be used to perform reflection.
2163 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
2164 public static Type
GetReflectionType(Type type
)
2168 throw new ArgumentNullException("type");
2171 return NodeFor(type
).GetReflectionType(type
);
2175 /// Returns an Type instance that can be used to perform reflection.
2177 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
2178 public static Type
GetReflectionType(object instance
)
2180 if (instance
== null)
2182 throw new ArgumentNullException("instance");
2185 return NodeFor(instance
).GetReflectionType(instance
);
2189 /// Retrieves the head type description node for a type.
2190 /// A head node pointing to a reflection based type description
2191 /// provider will be created on demand. This does not create
2192 /// a delegator, in which case the node returned may be
2193 /// a base type node.
2195 private static TypeDescriptionNode
NodeFor(Type type
) {
2196 return NodeFor(type
, false);
2200 /// Retrieves the head type description node for a type.
2201 /// A head node pointing to a reflection based type description
2202 /// provider will be created on demand.
2204 /// If createDelegator is true, this method will create a delegation
2205 /// node for a type if the type has no node of its own. Delegation
2206 /// nodes should be created if you are going to hand this node
2207 /// out to a user. Without a delegation node, user code could
2208 /// skip providers that are added after their call. Delegation
2209 /// nodes solve that problem.
2211 /// If createDelegator is false, this method will recurse up the
2212 /// base type chain looking for nodes.
2214 private static TypeDescriptionNode
NodeFor(Type type
, bool createDelegator
) {
2215 Debug
.Assert(type
!= null, "Caller should validate");
2216 CheckDefaultProvider(type
);
2218 // First, check our provider type table to see if we have a matching
2219 // provider for this type. The provider type table is a cache that
2220 // matches types to providers. When a new provider is added or
2221 // an existing one removed, the provider type table is torn
2222 // down and automatically rebuilt on demand.
2224 TypeDescriptionNode node
= null;
2225 Type searchType
= type
;
2227 while (node
== null) {
2228 node
= (TypeDescriptionNode
)_providerTypeTable
[searchType
];
2230 node
= (TypeDescriptionNode
)_providerTable
[searchType
];
2234 Type baseType
= GetNodeForBaseType(searchType
);
2236 if (searchType
== typeof(object) || baseType
== null) {
2238 lock (_providerTable
) {
2239 node
= (TypeDescriptionNode
)_providerTable
[searchType
];
2242 // The reflect type description provider is a default provider that
2243 // can provide type information for all objects.
2244 node
= new TypeDescriptionNode(new ReflectTypeDescriptionProvider());
2245 _providerTable
[searchType
] = node
;
2246 Trace("Nodes : Allocated new type node. Now {0} nodes", _providerTable
.Count
);
2251 else if (createDelegator
) {
2252 node
= new TypeDescriptionNode(new DelegatingTypeDescriptionProvider(baseType
));
2253 lock (_providerTable
) {
2254 _providerTypeTable
[searchType
] = node
;
2258 // Continue our search
2259 searchType
= baseType
;
2268 /// Retrieves the head type description node for an instance.
2269 /// Instance-based node lists are rare. If a node list is not
2270 /// available for a given instance, this will return the head node
2271 /// for the instance's type.
2273 private static TypeDescriptionNode
NodeFor(object instance
)
2275 return NodeFor(instance
, false);
2279 /// Retrieves the head type description node for an instance.
2280 /// Instance-based node lists are rare. If a node list is not
2281 /// available for a given instance, this will return the head node
2282 /// for the instance's type. This variation offers a bool called
2283 /// createDelegator. If true and there is no node list for this
2284 /// instance, NodeFor will create a temporary "delegator node" that,
2285 /// when queried, will delegate to the type stored in the instance.
2286 /// This is done on demand, which means if someone else added a
2287 /// type description provider for the instance's type the delegator
2288 /// would pick up the new type. If a query is being made that does
2289 /// not involve publicly exposing the type description provider for
2290 /// the instance, the query should pass in fase (the default) for
2291 /// createDelegator because no object will be created.
2293 private static TypeDescriptionNode
NodeFor(object instance
, bool createDelegator
)
2295 // For object instances, the provider cache key is not the object (that
2296 // would keep it in memory). Instead, it is a subclass of WeakReference
2297 // that overrides GetHashCode and Equals to make it appear to be the
2298 // object it is wrapping. A GC'd object causes WeakReference to return
2299 // false for all .Equals, but it always returns a valid hash code.
2301 Debug
.Assert(instance
!= null, "Caller should validate");
2303 TypeDescriptionNode node
= (TypeDescriptionNode
)_providerTable
[instance
];
2306 Type type
= instance
.GetType();
2308 if (type
.IsCOMObject
)
2310 type
= ComObjectType
;
2313 if (createDelegator
)
2315 node
= new TypeDescriptionNode(new DelegatingTypeDescriptionProvider(type
));
2316 Trace("Nodes : Allocated new instance node for {0}. Now {1} nodes", type
.Name
, _providerTable
.Count
);
2320 node
= NodeFor(type
);
2328 /// Simple linked list code to remove an element
2329 /// from the list. Returns the new head to the
2330 /// list. If the head points to an instance of
2331 /// DelegatingTypeDescriptionProvider, we clear the
2332 /// node because all it is doing is delegating elsewhere.
2334 /// Note that this behaves a little differently from normal
2335 /// linked list code. In a normal linked list, you remove
2336 /// then target node and fixup the links. In this linked
2337 /// list, we remove the node AFTER the target node, fixup
2338 /// the links, and fixup the underlying providers that each
2339 /// node references. The reason for this is that most
2340 /// providers keep a reference to the previous provider,
2341 /// which is exposed as one of these nodes. Therefore,
2342 /// to remove a provider the node following is most likely
2343 /// referenced by that provider
2345 private static void NodeRemove(object key
, TypeDescriptionProvider provider
)
2347 lock(_providerTable
)
2349 TypeDescriptionNode head
= (TypeDescriptionNode
)_providerTable
[key
];
2350 TypeDescriptionNode target
= head
;
2351 TypeDescriptionNode prev
= null;
2353 while(target
!= null && target
.Provider
!= provider
)
2356 target
= target
.Next
;
2361 // We have our target node. There are three cases
2362 // to consider: the target is in the middle, the head,
2365 if (target
.Next
!= null) {
2366 // If there is a node after the target node,
2367 // steal the node's provider and store it
2368 // at the target location. This removes
2369 // the provider at the target location without
2370 // the need to modify providers which may be
2371 // pointing to "target".
2372 target
.Provider
= target
.Next
.Provider
;
2374 // Now remove target.Next from the list
2375 target
.Next
= target
.Next
.Next
;
2377 // If the new provider we got is a delegating
2378 // provider, we can remove this node from
2379 // the list. The delegating provider should
2380 // always be at the end of the node list.
2381 if (target
== head
&& target
.Provider
is DelegatingTypeDescriptionProvider
) {
2382 Debug
.Assert(target
.Next
== null, "Delegating provider should always be the last provider in the chain.");
2383 _providerTable
.Remove(key
);
2386 else if (target
!= head
) {
2387 // If target is the last node, we can't
2388 // assign a new provider over to it. What
2389 // we can do, however, is assign a delegating
2390 // provider into the target node. This routes
2391 // requests from the previous provider into
2392 // the next base type provider list.
2394 // We don't do this if the target is the head.
2395 // In that case, we can remove the node
2396 // altogether since no one is pointing to it.
2398 Type keyType
= key
as Type
;
2399 if (keyType
== null) keyType
= key
.GetType();
2401 target
.Provider
= new DelegatingTypeDescriptionProvider(keyType
.BaseType
);
2404 _providerTable
.Remove(key
);
2407 // Finally, clear our cache of provider types; it might be invalid
2409 _providerTypeTable
.Clear();
2415 /// This is the last stage in our filtering pipeline. Here, we apply any
2416 /// user-defined filter.
2418 private static ICollection
PipelineAttributeFilter(int pipelineType
, ICollection members
, Attribute
[] filter
, object instance
, IDictionary cache
)
2420 Debug
.Assert(pipelineType
!= PIPELINE_ATTRIBUTES
, "PipelineAttributeFilter is not supported for attributes");
2422 IList list
= members
as ArrayList
;
2424 if (filter
== null || filter
.Length
== 0)
2429 // Now, check our cache. The cache state is only valid
2430 // if the data coming into us is read-only. If it is read-write,
2431 // that means something higher in the pipeline has already changed
2432 // it so we must recompute anyway.
2434 if (cache
!= null && (list
== null || list
.IsReadOnly
))
2436 AttributeFilterCacheItem filterCache
= cache
[_pipelineAttributeFilterKeys
[pipelineType
]] as AttributeFilterCacheItem
;
2437 if (filterCache
!= null && filterCache
.IsValid(filter
))
2439 return filterCache
.FilteredMembers
;
2443 // Our cache did not contain the correct state, so generate it.
2445 if (list
== null || list
.IsReadOnly
)
2447 Trace("Pipeline : Filter needs to create member list for {0}", instance
.GetType().Name
);
2448 list
= new ArrayList(members
);
2451 ArrayList filterResult
= FilterMembers(list
, filter
);
2452 if (filterResult
!= null) list
= filterResult
;
2454 // And, if we have a cache, store the updated state into it for future reference.
2458 ICollection cacheValue
;
2460 switch(pipelineType
)
2462 case PIPELINE_PROPERTIES
:
2463 PropertyDescriptor
[] propArray
= new PropertyDescriptor
[list
.Count
];
2464 list
.CopyTo(propArray
, 0);
2465 cacheValue
= new PropertyDescriptorCollection(propArray
, true);
2468 case PIPELINE_EVENTS
:
2469 EventDescriptor
[] eventArray
= new EventDescriptor
[list
.Count
];
2470 list
.CopyTo(eventArray
, 0);
2471 cacheValue
= new EventDescriptorCollection(eventArray
, true);
2475 Debug
.Fail("unknown pipeline type");
2480 Trace("Pipeline : Attribute Filter results being cached for {0}", instance
.GetType().Name
);
2481 AttributeFilterCacheItem filterCache
= new AttributeFilterCacheItem(filter
, cacheValue
);
2482 cache
[_pipelineAttributeFilterKeys
[pipelineType
]] = filterCache
;
2489 /// Metdata filtering is the third stage of our pipeline.
2490 /// In this stage we check to see if the given object is a
2491 /// sited component that provides the ITypeDescriptorFilterService
2492 /// object. If it does, we allow the TDS to filter the metadata.
2493 /// This will use the cache, if available, to store filtered
2496 private static ICollection
PipelineFilter(int pipelineType
, ICollection members
, object instance
, IDictionary cache
)
2498 IComponent component
= instance
as IComponent
;
2499 ITypeDescriptorFilterService componentFilter
= null;
2501 if (component
!= null)
2503 ISite site
= component
.Site
;
2506 componentFilter
= site
.GetService(typeof(ITypeDescriptorFilterService
)) as ITypeDescriptorFilterService
;
2510 // If we have no filter, there is nothing for us to do.
2512 IList list
= members
as ArrayList
;
2514 if (componentFilter
== null)
2516 Debug
.Assert(cache
== null || list
== null || !cache
.Contains(_pipelineFilterKeys
[pipelineType
]), "Earlier pipeline stage should have removed our cache");
2520 // Now, check our cache. The cache state is only valid
2521 // if the data coming into us is read-only. If it is read-write,
2522 // that means something higher in the pipeline has already changed
2523 // it so we must recompute anyway.
2525 if (cache
!= null && (list
== null || list
.IsReadOnly
))
2527 FilterCacheItem cacheItem
= cache
[_pipelineFilterKeys
[pipelineType
]] as FilterCacheItem
;
2528 if (cacheItem
!= null && cacheItem
.IsValid(componentFilter
)) {
2529 return cacheItem
.FilteredMembers
;
2533 // Cache either is dirty or doesn't exist. Re-filter the members.
2534 // We need to build an IDictionary of key->value pairs and invoke
2535 // Filter* on the filter service.
2537 OrderedDictionary filterTable
= new OrderedDictionary(members
.Count
);
2540 switch(pipelineType
)
2542 case PIPELINE_ATTRIBUTES
:
2543 foreach(Attribute attr
in members
)
2545 filterTable
[attr
.TypeId
] = attr
;
2547 cacheResults
= componentFilter
.FilterAttributes(component
, filterTable
);
2550 case PIPELINE_PROPERTIES
:
2551 case PIPELINE_EVENTS
:
2552 foreach(MemberDescriptor desc
in members
)
2554 string descName
= desc
.Name
;
2555 // We must handle the case of duplicate property names
2556 // because extender providers can provide any arbitrary
2557 // name. Our rule for this is simple: If we find a
2558 // duplicate name, resolve it back to the extender
2559 // provider that offered it and append "_" + the
2560 // provider name. If the provider has no name,
2561 // then append the object hash code.
2563 if (filterTable
.Contains(descName
))
2565 // First, handle the new property. Because
2566 // of the order in which we added extended
2567 // properties earlier in the pipeline, we can be
2568 // sure that the new property is an extender. We
2569 // cannot be sure that the existing property
2570 // in the table is an extender, so we will
2573 string suffix
= GetExtenderCollisionSuffix(desc
);
2574 Debug
.Assert(suffix
!= null, "Name collision with non-extender property.");
2577 filterTable
[descName
+ suffix
] = desc
;
2580 // Now, handle the original property.
2582 MemberDescriptor origDesc
= (MemberDescriptor
)filterTable
[descName
];
2583 suffix
= GetExtenderCollisionSuffix(origDesc
);
2586 filterTable
.Remove(descName
);
2587 filterTable
[origDesc
.Name
+ suffix
] = origDesc
;
2592 filterTable
[descName
] = desc
;
2595 if (pipelineType
== PIPELINE_PROPERTIES
)
2597 cacheResults
= componentFilter
.FilterProperties(component
, filterTable
);
2601 cacheResults
= componentFilter
.FilterEvents(component
, filterTable
);
2606 Debug
.Fail("unknown pipeline type");
2607 cacheResults
= false;
2611 // See if we can re-use the IList were were passed. If we can,
2612 // it is more efficient to re-use its slots than to generate new ones.
2614 if (list
== null || list
.IsReadOnly
)
2616 Trace("Pipeline : Filter needs to create member list for {0}", instance
.GetType().Name
);
2617 list
= new ArrayList(filterTable
.Values
);
2622 foreach(object obj
in filterTable
.Values
)
2628 // Component filter has requested that we cache these
2629 // new changes. We store them as a correctly typed collection
2630 // so on successive invocations we can simply return. Note that
2631 // we always return the IList so that successive stages in the
2632 // pipeline can modify it.
2634 if (cacheResults
&& cache
!= null)
2636 ICollection cacheValue
;
2638 switch(pipelineType
)
2640 case PIPELINE_ATTRIBUTES
:
2641 Attribute
[] attrArray
= new Attribute
[list
.Count
];
2644 list
.CopyTo(attrArray
, 0);
2646 catch(InvalidCastException
)
2648 throw new ArgumentException(SR
.GetString(SR
.TypeDescriptorExpectedElementType
, typeof(Attribute
).FullName
));
2650 cacheValue
= new AttributeCollection(attrArray
);
2653 case PIPELINE_PROPERTIES
:
2654 PropertyDescriptor
[] propArray
= new PropertyDescriptor
[list
.Count
];
2657 list
.CopyTo(propArray
, 0);
2659 catch(InvalidCastException
)
2661 throw new ArgumentException(SR
.GetString(SR
.TypeDescriptorExpectedElementType
, typeof(PropertyDescriptor
).FullName
));
2663 cacheValue
= new PropertyDescriptorCollection(propArray
, true);
2666 case PIPELINE_EVENTS
:
2667 EventDescriptor
[] eventArray
= new EventDescriptor
[list
.Count
];
2670 list
.CopyTo(eventArray
, 0);
2672 catch(InvalidCastException
)
2674 throw new ArgumentException(SR
.GetString(SR
.TypeDescriptorExpectedElementType
, typeof(EventDescriptor
).FullName
));
2676 cacheValue
= new EventDescriptorCollection(eventArray
, true);
2680 Debug
.Fail("unknown pipeline type");
2685 Trace("Pipeline : Filter results being cached for {0}", instance
.GetType().Name
);
2687 FilterCacheItem cacheItem
= new FilterCacheItem(componentFilter
, cacheValue
);
2688 cache
[_pipelineFilterKeys
[pipelineType
]] = cacheItem
;
2689 cache
.Remove(_pipelineAttributeFilterKeys
[pipelineType
]);
2696 /// This is the first stage in the pipeline. This checks the incoming member collection and if it
2697 /// differs from what we have seen in the past, it invalidates all successive pipelines.
2699 private static ICollection
PipelineInitialize (int pipelineType
, ICollection members
, IDictionary cache
) {
2700 if (cache
!= null) {
2702 bool cacheValid
= true;
2704 ICollection cachedMembers
= cache
[_pipelineInitializeKeys
[pipelineType
]] as ICollection
;
2705 if (cachedMembers
!= null && cachedMembers
.Count
== members
.Count
) {
2706 IEnumerator cacheEnum
= cachedMembers
.GetEnumerator();
2707 IEnumerator memberEnum
= members
.GetEnumerator();
2709 while(cacheEnum
.MoveNext() && memberEnum
.MoveNext()) {
2710 if (cacheEnum
.Current
!= memberEnum
.Current
) {
2718 // The cache wasn't valid. Remove all subsequent cache layers
2719 // and then save off new data.
2720 cache
.Remove(_pipelineMergeKeys
[pipelineType
]);
2721 cache
.Remove(_pipelineFilterKeys
[pipelineType
]);
2722 cache
.Remove(_pipelineAttributeFilterKeys
[pipelineType
]);
2723 cache
[_pipelineInitializeKeys
[pipelineType
]] = members
;
2731 /// Metadata merging is the second stage of our metadata pipeline. This stage
2732 /// merges extended metdata with primary metadata, and stores it in
2733 /// the cache if it is available.
2735 private static ICollection
PipelineMerge(int pipelineType
, ICollection primary
, ICollection secondary
, object instance
, IDictionary cache
)
2737 // If there is no secondary collection, there is nothing to merge.
2739 if (secondary
== null || secondary
.Count
== 0)
2744 // Next, if we were given a cache, see if it has accurate data.
2748 ICollection mergeCache
= cache
[_pipelineMergeKeys
[pipelineType
]] as ICollection
;
2749 if (mergeCache
!= null && mergeCache
.Count
== (primary
.Count
+ secondary
.Count
))
2751 // Walk the merge cache.
2752 IEnumerator mergeEnum
= mergeCache
.GetEnumerator();
2753 IEnumerator primaryEnum
= primary
.GetEnumerator();
2756 while(primaryEnum
.MoveNext() && mergeEnum
.MoveNext())
2758 if (primaryEnum
.Current
!= mergeEnum
.Current
)
2767 IEnumerator secondaryEnum
= secondary
.GetEnumerator();
2769 while(secondaryEnum
.MoveNext() && mergeEnum
.MoveNext())
2771 if (secondaryEnum
.Current
!= mergeEnum
.Current
)
2786 // Our cache didn't match. We need to merge metadata and return
2787 // the merged copy. We create an array list here, rather than
2788 // an array, because we want successive sections of the
2789 // pipeline to be able to modify it.
2791 ArrayList list
= new ArrayList(primary
.Count
+ secondary
.Count
);
2792 foreach(object obj
in primary
)
2796 foreach(object obj
in secondary
)
2803 ICollection cacheValue
;
2805 switch(pipelineType
)
2807 case PIPELINE_ATTRIBUTES
:
2808 Attribute
[] attrArray
= new Attribute
[list
.Count
];
2809 list
.CopyTo(attrArray
, 0);
2810 cacheValue
= new AttributeCollection(attrArray
);
2813 case PIPELINE_PROPERTIES
:
2814 PropertyDescriptor
[] propArray
= new PropertyDescriptor
[list
.Count
];
2815 list
.CopyTo(propArray
, 0);
2816 cacheValue
= new PropertyDescriptorCollection(propArray
, true);
2819 case PIPELINE_EVENTS
:
2820 EventDescriptor
[] eventArray
= new EventDescriptor
[list
.Count
];
2821 list
.CopyTo(eventArray
, 0);
2822 cacheValue
= new EventDescriptorCollection(eventArray
, true);
2826 Debug
.Fail("unknown pipeline type");
2831 Trace("Pipeline : Merge results being cached for {0}", instance
.GetType().Name
);
2832 cache
[_pipelineMergeKeys
[pipelineType
]] = cacheValue
;
2833 cache
.Remove(_pipelineFilterKeys
[pipelineType
]);
2834 cache
.Remove(_pipelineAttributeFilterKeys
[pipelineType
]);
2840 private static void RaiseRefresh(object component
) {
2841 // This volatility prevents the JIT from making certain optimizations
2842 // that could cause this firing pattern to break. Although the likelihood
2843 // the JIT makes those changes is mostly theoretical
2844 RefreshEventHandler handler
= Volatile
.Read(ref Refreshed
);
2846 if (handler
!= null)
2848 handler(new RefreshEventArgs(component
));
2852 private static void RaiseRefresh(Type type
) {
2853 RefreshEventHandler handler
= Volatile
.Read(ref Refreshed
);
2855 if (handler
!= null)
2857 handler(new RefreshEventArgs(type
));
2862 /// Clears the properties and events for the specified
2863 /// component from the cache.
2865 public static void Refresh(object component
)
2867 Refresh(component
, true);
2870 private static void Refresh(object component
, bool refreshReflectionProvider
) {
2872 DebugTypeDescriptor
.Refresh(component
);
2875 if (component
== null)
2877 Debug
.Fail("COMPAT: Returning, but you should not pass null here");
2881 // Build up a list of type description providers for
2882 // each type that is a derived type of the given
2883 // object. We will invalidate the metadata at
2884 // each of these levels.
2887 if (refreshReflectionProvider
)
2889 Type type
= component
.GetType();
2891 lock (_providerTable
)
2893 // ReflectTypeDescritionProvider is only bound to object, but we
2894 // need go to through the entire table to try to find custom
2895 // providers. If we find one, will clear our cache.
2896 foreach (DictionaryEntry de
in _providerTable
)
2898 Type nodeType
= de
.Key
as Type
;
2899 if (nodeType
!= null && type
.IsAssignableFrom(nodeType
) || nodeType
== typeof(object))
2901 TypeDescriptionNode node
= (TypeDescriptionNode
)de
.Value
;
2902 while (node
!= null && !(node
.Provider
is ReflectTypeDescriptionProvider
))
2910 ReflectTypeDescriptionProvider provider
= (ReflectTypeDescriptionProvider
)node
.Provider
;
2911 if (provider
.IsPopulated(type
))
2914 provider
.Refresh(type
);
2922 // We need to clear our filter even if no typedescriptionprovider had data.
2923 // This is because if you call Refresh(instance1) and Refresh(instance2)
2924 // and instance1 and instance2 are of the same type, you will end up not
2925 // actually deleting the dictionary cache on instance2 if you skip this
2926 // when you don't find a typedescriptionprovider.
2927 // However, we do not need to fire the event if we did not find any loaded
2928 // typedescriptionprovider AND the cache is empty (if someone repeatedly calls
2929 // Refresh on an instance).
2931 // Now, clear any cached data for the instance.
2933 IDictionary cache
= GetCache(component
);
2934 if (found
|| cache
!= null)
2938 Trace("Pipeline : Refresh clearing all pipeline caches");
2939 for (int idx
= 0; idx
< _pipelineFilterKeys
.Length
; idx
++)
2941 cache
.Remove(_pipelineFilterKeys
[idx
]);
2942 cache
.Remove(_pipelineMergeKeys
[idx
]);
2943 cache
.Remove(_pipelineAttributeFilterKeys
[idx
]);
2948 Interlocked
.Increment(ref _metadataVersion
);
2950 // And raise the event.
2952 RaiseRefresh(component
);
2957 /// Clears the properties and events for the specified type
2958 /// of component from the cache.
2960 public static void Refresh(Type type
)
2963 DebugTypeDescriptor
.Refresh(type
);
2968 Debug
.Fail("COMPAT: Returning, but you should not pass null here");
2972 // Build up a list of type description providers for
2973 // each type that is a derived type of the given
2974 // type. We will invalidate the metadata at
2975 // each of these levels.
2979 lock(_providerTable
)
2981 // ReflectTypeDescritionProvider is only bound to object, but we
2982 // need go to through the entire table to try to find custom
2983 // providers. If we find one, will clear our cache.
2984 foreach(DictionaryEntry de
in _providerTable
)
2986 Type nodeType
= de
.Key
as Type
;
2987 if (nodeType
!= null && type
.IsAssignableFrom(nodeType
) || nodeType
== typeof(object))
2989 TypeDescriptionNode node
= (TypeDescriptionNode
)de
.Value
;
2990 while(node
!= null && !(node
.Provider
is ReflectTypeDescriptionProvider
))
2998 ReflectTypeDescriptionProvider provider
= (ReflectTypeDescriptionProvider
)node
.Provider
;
2999 if (provider
.IsPopulated(type
))
3002 provider
.Refresh(type
);
3009 // We only clear our filter and fire the refresh event if there was one or
3010 // more type description providers that were populated with metdata.
3011 // This prevents us from doing a lot of extra work and raising
3012 // a ton more events than we need to.
3016 Interlocked
.Increment(ref _metadataVersion
);
3018 // And raise the event.
3025 /// Clears the properties and events for the specified
3026 /// module from the cache.
3028 public static void Refresh(Module module
)
3031 DebugTypeDescriptor
.Refresh(module
);
3036 Debug
.Fail("COMPAT: Returning, but you should not pass null here");
3040 // Build up a list of type description providers for
3041 // each type that is a derived type of the given
3042 // object. We will invalidate the metadata at
3043 // each of these levels.
3044 Hashtable refreshedTypes
= null;
3046 lock(_providerTable
)
3048 foreach(DictionaryEntry de
in _providerTable
)
3050 Type nodeType
= de
.Key
as Type
;
3051 if (nodeType
!= null && nodeType
.Module
.Equals(module
) || nodeType
== typeof(object))
3053 TypeDescriptionNode node
= (TypeDescriptionNode
)de
.Value
;
3054 while(node
!= null && !(node
.Provider
is ReflectTypeDescriptionProvider
))
3056 if (refreshedTypes
== null) {
3057 refreshedTypes
= new Hashtable();
3059 refreshedTypes
[nodeType
] = nodeType
;
3065 ReflectTypeDescriptionProvider provider
= (ReflectTypeDescriptionProvider
)node
.Provider
;
3066 Type
[] populatedTypes
= provider
.GetPopulatedTypes(module
);
3068 foreach(Type populatedType
in populatedTypes
) {
3069 provider
.Refresh(populatedType
);
3070 if (refreshedTypes
== null) {
3071 refreshedTypes
= new Hashtable();
3073 refreshedTypes
[populatedType
] = populatedType
;
3080 // And raise the event if types were refresh and handlers are attached.
3082 if (refreshedTypes
!= null && Refreshed
!= null)
3084 foreach(Type t
in refreshedTypes
.Keys
) {
3091 /// Clears the properties and events for the specified
3092 /// assembly from the cache.
3094 [ResourceExposure(ResourceScope
.None
)]
3095 [ResourceConsumption(ResourceScope
.Machine
| ResourceScope
.Assembly
, ResourceScope
.Machine
| ResourceScope
.Assembly
)]
3096 public static void Refresh(Assembly assembly
)
3098 if (assembly
== null)
3100 Debug
.Fail("COMPAT: Returning, but you should not pass null here");
3104 foreach (Module mod
in assembly
.GetModules())
3109 // Debug type descriptor has the same code, so our call above will handle this.
3113 /// The RemoveAssociation method removes an association with an object.
3115 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
3116 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
3117 public static void RemoveAssociation(object primary
, object secondary
)
3119 if (primary
== null)
3121 throw new ArgumentNullException("primary");
3124 if (secondary
== null)
3126 throw new ArgumentNullException("secondary");
3129 Hashtable assocTable
= _associationTable
;
3130 if (assocTable
!= null)
3132 IList associations
= (IList
)assocTable
[primary
];
3133 if (associations
!= null)
3137 for (int idx
= associations
.Count
- 1; idx
>= 0; idx
--)
3139 // Look for an associated object that has a type that
3140 // matches the given type.
3142 WeakReference weakRef
= (WeakReference
)associations
[idx
];
3143 object secondaryItem
= weakRef
.Target
;
3144 if (secondaryItem
== null || secondaryItem
== secondary
)
3146 associations
.RemoveAt(idx
);
3155 /// The RemoveAssociations method removes all associations for a primary object.
3157 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
3158 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
3159 public static void RemoveAssociations(object primary
)
3161 if (primary
== null)
3163 throw new ArgumentNullException("primary");
3166 Hashtable assocTable
= _associationTable
;
3167 if (assocTable
!= null)
3169 assocTable
.Remove(primary
);
3174 /// The RemoveProvider method removes a previously added type
3175 /// description provider. Removing a provider causes a Refresh
3176 /// event to be raised for the object or type the provider is
3177 /// associated with.
3179 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
3180 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
3181 public static void RemoveProvider(TypeDescriptionProvider provider
, Type type
)
3183 if (provider
== null)
3185 throw new ArgumentNullException("provider");
3190 throw new ArgumentNullException("type");
3193 // Walk the nodes until we find the right one, and then remove it.
3194 NodeRemove(type
, provider
);
3199 /// The RemoveProvider method removes a previously added type
3200 /// description provider. Removing a provider causes a Refresh
3201 /// event to be raised for the object or type the provider is
3202 /// associated with.
3204 [System
.Security
.Permissions
.PermissionSetAttribute(System
.Security
.Permissions
.SecurityAction
.LinkDemand
, Name
="FullTrust")]
3205 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
3206 public static void RemoveProvider(TypeDescriptionProvider provider
, object instance
)
3208 if (provider
== null)
3210 throw new ArgumentNullException("provider");
3213 if (instance
== null)
3215 throw new ArgumentNullException("instance");
3218 // Walk the nodes until we find the right one, and then remove it.
3219 NodeRemove(instance
, provider
);
3220 RaiseRefresh(instance
);
3225 /// The RemoveProvider method removes a previously added type
3226 /// description provider. Removing a provider causes a Refresh
3227 /// event to be raised for the object or type the provider is
3228 /// associated with.
3230 /// This method can be called from partially trusted code. If
3231 /// <see cref="TypeDescriptorPermissionFlags.RestrictedRegistrationAccess"/>
3232 /// is defined, the caller can unregister a provider for the specified type
3233 /// if it's also partially trusted.
3235 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
3236 public static void RemoveProviderTransparent(TypeDescriptionProvider provider
, Type type
)
3238 if (provider
== null)
3240 throw new ArgumentNullException("provider");
3245 throw new ArgumentNullException("type");
3247 #if !DISABLE_CAS_USE
3248 PermissionSet typeDescriptorPermission
= new PermissionSet(PermissionState
.None
);
3249 typeDescriptorPermission
.AddPermission(new TypeDescriptorPermission(TypeDescriptorPermissionFlags
.RestrictedRegistrationAccess
));
3251 PermissionSet targetPermissions
= type
.Assembly
.PermissionSet
;
3252 targetPermissions
= targetPermissions
.Union(typeDescriptorPermission
);
3254 targetPermissions
.Demand();
3256 RemoveProvider(provider
, type
);
3260 /// The RemoveProvider method removes a previously added type
3261 /// description provider. Removing a provider causes a Refresh
3262 /// event to be raised for the object or type the provider is
3263 /// associated with.
3265 /// This method can be called from partially trusted code. If
3266 /// <see cref="TypeDescriptorPermissionFlags.RestrictedRegistrationAccess"/>
3267 /// is defined, the caller can register a provider for the specified instance
3268 /// if its type is also partially trusted.
3270 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
3271 public static void RemoveProviderTransparent(TypeDescriptionProvider provider
, object instance
)
3273 if (provider
== null)
3275 throw new ArgumentNullException("provider");
3278 if (instance
== null)
3280 throw new ArgumentNullException("instance");
3282 #if !DISABLE_CAS_USE
3283 Type type
= instance
.GetType();
3285 PermissionSet typeDescriptorPermission
= new PermissionSet(PermissionState
.None
);
3286 typeDescriptorPermission
.AddPermission(new TypeDescriptorPermission(TypeDescriptorPermissionFlags
.RestrictedRegistrationAccess
));
3288 PermissionSet targetPermissions
= type
.Assembly
.PermissionSet
;
3289 targetPermissions
= targetPermissions
.Union(typeDescriptorPermission
);
3291 targetPermissions
.Demand();
3293 RemoveProvider(provider
, instance
);
3297 /// This function takes a member descriptor and an attribute and determines whether
3298 /// the member satisfies the particular attribute. This either means that the member
3299 /// contains the attribute or the member does not contain the attribute and the default
3300 /// for the attribute matches the passed in attribute.
3302 private static bool ShouldHideMember(MemberDescriptor member
, Attribute attribute
)
3304 if (member
== null || attribute
== null)
3309 Attribute memberAttribute
= member
.Attributes
[attribute
.GetType()];
3310 if (memberAttribute
== null)
3312 return !attribute
.IsDefaultAttribute();
3316 return !(attribute
.Match(memberAttribute
));
3321 /// Sorts descriptors by name of the descriptor.
3323 public static void SortDescriptorArray(IList infos
)
3327 throw new ArgumentNullException("infos");
3330 ArrayList
.Adapter(infos
).Sort(MemberDescriptorComparer
.Instance
);
3334 /// Internal tracing API for debugging type descriptor.
3336 [Conditional("DEBUG")]
3337 internal static void Trace(string message
, params object[] args
)
3339 Debug
.WriteLineIf(TraceDescriptor
.Enabled
, string.Format(CultureInfo
.InvariantCulture
, "TypeDescriptor : {0}", string.Format(CultureInfo
.InvariantCulture
, message
, args
)));
3343 /// This is a type description provider that adds the given
3344 /// array of attributes to a class or instance, preserving the rest
3345 /// of the metadata in the process.
3347 private sealed class AttributeProvider
: TypeDescriptionProvider
3352 /// Creates a new attribute provider.
3354 internal AttributeProvider(TypeDescriptionProvider existingProvider
, params Attribute
[] attrs
) : base(existingProvider
)
3360 /// Creates a custom type descriptor that replaces the attributes.
3362 public override ICustomTypeDescriptor
GetTypeDescriptor(Type objectType
, object instance
)
3364 return new AttributeTypeDescriptor(_attrs
, base.GetTypeDescriptor(objectType
, instance
));
3368 /// Our custom type descriptor.
3370 private class AttributeTypeDescriptor
: CustomTypeDescriptor
3372 Attribute
[] _attributeArray
;
3375 /// Creates a new custom type descriptor that can merge
3376 /// the provided set of attributes with the existing set.
3378 internal AttributeTypeDescriptor(Attribute
[] attrs
, ICustomTypeDescriptor parent
) : base(parent
)
3380 _attributeArray
= attrs
;
3384 /// Retrieves the merged set of attributes. We do not cache
3385 /// this because there is always the possibility that someone
3386 /// changed our parent provider's metadata. TypeDescriptor
3387 /// will cache this for us anyhow.
3389 public override AttributeCollection
GetAttributes()
3391 Attribute
[] finalAttr
= null;
3392 AttributeCollection existing
= base.GetAttributes();
3393 Attribute
[] newAttrs
= _attributeArray
;
3394 Attribute
[] newArray
= new Attribute
[existing
.Count
+ newAttrs
.Length
];
3395 int actualCount
= existing
.Count
;
3396 existing
.CopyTo(newArray
, 0);
3398 for (int idx
= 0; idx
< newAttrs
.Length
; idx
++)
3401 Debug
.Assert(newAttrs
[idx
] != null, "_attributes contains a null member");
3403 // We must see if this attribute is already in the existing
3404 // array. If it is, we replace it.
3406 for (int existingIdx
= 0; existingIdx
< existing
.Count
; existingIdx
++)
3408 if (newArray
[existingIdx
].TypeId
.Equals(newAttrs
[idx
].TypeId
))
3411 newArray
[existingIdx
] = newAttrs
[idx
];
3418 newArray
[actualCount
++] = newAttrs
[idx
];
3422 // Now, if we collapsed some attributes, create a new array.
3424 if (actualCount
< newArray
.Length
)
3426 finalAttr
= new Attribute
[actualCount
];
3427 Array
.Copy(newArray
, 0, finalAttr
, 0, actualCount
);
3431 finalAttr
= newArray
;
3434 return new AttributeCollection(finalAttr
);
3440 /// This class is a type description provider that works with the IComNativeDescriptorHandler
3443 private sealed class ComNativeDescriptionProvider
: TypeDescriptionProvider
3445 #pragma warning disable 618
3446 private IComNativeDescriptorHandler _handler
;
3448 internal ComNativeDescriptionProvider(IComNativeDescriptorHandler handler
)
3454 /// Returns the COM handler object.
3456 internal IComNativeDescriptorHandler Handler
3467 #pragma warning restore 618
3470 /// Implements GetTypeDescriptor. This creates a custom type
3471 /// descriptor that walks the linked list for each of its calls.
3474 [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")]
3475 public override ICustomTypeDescriptor
GetTypeDescriptor(Type objectType
, object instance
)
3477 if (objectType
== null)
3479 throw new ArgumentNullException("objectType");
3482 if (instance
== null)
3487 if (!objectType
.IsInstanceOfType(instance
))
3489 throw new ArgumentException("instance");
3492 return new ComNativeTypeDescriptor(_handler
, instance
);
3496 /// This type descriptor sits on top of a native
3497 /// descriptor handler.
3499 private sealed class ComNativeTypeDescriptor
: ICustomTypeDescriptor
3501 #pragma warning disable 618
3502 private IComNativeDescriptorHandler _handler
;
3503 private object _instance
;
3506 /// Creates a new ComNativeTypeDescriptor.
3508 internal ComNativeTypeDescriptor(IComNativeDescriptorHandler handler
, object instance
)
3511 _instance
= instance
;
3513 #pragma warning restore 618
3516 /// ICustomTypeDescriptor implementation.
3518 AttributeCollection ICustomTypeDescriptor
.GetAttributes()
3520 return _handler
.GetAttributes(_instance
);
3524 /// ICustomTypeDescriptor implementation.
3526 string ICustomTypeDescriptor
.GetClassName()
3528 return _handler
.GetClassName(_instance
);
3532 /// ICustomTypeDescriptor implementation.
3534 string ICustomTypeDescriptor
.GetComponentName()
3540 /// ICustomTypeDescriptor implementation.
3542 TypeConverter ICustomTypeDescriptor
.GetConverter()
3544 return _handler
.GetConverter(_instance
);
3548 /// ICustomTypeDescriptor implementation.
3550 EventDescriptor ICustomTypeDescriptor
.GetDefaultEvent()
3552 return _handler
.GetDefaultEvent(_instance
);
3556 /// ICustomTypeDescriptor implementation.
3558 PropertyDescriptor ICustomTypeDescriptor
.GetDefaultProperty()
3560 return _handler
.GetDefaultProperty(_instance
);
3564 /// ICustomTypeDescriptor implementation.
3566 object ICustomTypeDescriptor
.GetEditor(Type editorBaseType
)
3568 return _handler
.GetEditor(_instance
, editorBaseType
);
3572 /// ICustomTypeDescriptor implementation.
3574 EventDescriptorCollection ICustomTypeDescriptor
.GetEvents()
3576 return _handler
.GetEvents(_instance
);
3580 /// ICustomTypeDescriptor implementation.
3582 EventDescriptorCollection ICustomTypeDescriptor
.GetEvents(Attribute
[] attributes
)
3584 return _handler
.GetEvents(_instance
, attributes
);
3588 /// ICustomTypeDescriptor implementation.
3590 PropertyDescriptorCollection ICustomTypeDescriptor
.GetProperties()
3592 return _handler
.GetProperties(_instance
, null);
3596 /// ICustomTypeDescriptor implementation.
3598 PropertyDescriptorCollection ICustomTypeDescriptor
.GetProperties(Attribute
[] attributes
)
3600 return _handler
.GetProperties(_instance
, attributes
);
3604 /// ICustomTypeDescriptor implementation.
3606 object ICustomTypeDescriptor
.GetPropertyOwner(PropertyDescriptor pd
)
3614 /// This is a simple class that is used to store a filtered
3615 /// set of members in an object's dictionary cache. It is
3616 /// used by the PipelineAttributeFilter method.
3618 private sealed class AttributeFilterCacheItem
3620 private Attribute
[] _filter
;
3621 internal ICollection FilteredMembers
;
3623 internal AttributeFilterCacheItem(Attribute
[] filter
, ICollection filteredMembers
)
3626 FilteredMembers
= filteredMembers
;
3629 internal bool IsValid(Attribute
[] filter
)
3631 if (_filter
.Length
!= filter
.Length
) return false;
3633 for (int idx
= 0; idx
< filter
.Length
; idx
++) {
3634 if (_filter
[idx
] != filter
[idx
]) {
3644 /// This small class contains cache information for the filter stage of our
3645 /// caching algorithm. It is used by the PipelineFilter method.
3647 private sealed class FilterCacheItem
{
3648 private ITypeDescriptorFilterService _filterService
;
3649 internal ICollection FilteredMembers
;
3651 internal FilterCacheItem(ITypeDescriptorFilterService filterService
, ICollection filteredMembers
) {
3652 _filterService
= filterService
;
3653 FilteredMembers
= filteredMembers
;
3656 internal bool IsValid(ITypeDescriptorFilterService filterService
) {
3657 if (!Object
.ReferenceEquals(_filterService
, filterService
)) return false;
3663 /// An unimplemented interface. What is this? It is an interface that nobody ever
3664 /// implements, of course? Where and why would it be used? Why, to find cross-process
3665 /// remoted objects, of course! If a well-known object comes in from a cross process
3666 /// connection, the remoting layer does contain enough type information to determine
3667 /// if an object implements an interface. It assumes that if you are going to cast
3668 /// an object to an interface that you know what you're doing, and allows the cast,
3669 /// even for objects that DON'T actually implement the interface. The error here
3670 /// is raised later when you make your first call on that interface pointer: you
3671 /// get a remoting exception.
3673 /// This is a big problem for code that does "is" and "as" checks to detect the
3674 /// presence of an interface. We do that all over the place here, so we do a check
3675 /// during parameter validation to see if an object implements IUnimplemented. If it
3676 /// does, we know that what we really have is a lying remoting proxy, and we bail.
3678 private interface IUnimplemented
{}
3681 /// This comparer compares member descriptors for sorting.
3683 private sealed class MemberDescriptorComparer
: IComparer
{
3684 public static readonly MemberDescriptorComparer Instance
= new MemberDescriptorComparer();
3686 public int Compare(object left
, object right
) {
3687 return string.Compare(((MemberDescriptor
)left
).Name
, ((MemberDescriptor
)right
).Name
, false, CultureInfo
.InvariantCulture
);
3692 /// This is a merged type descriptor that can merge the output of
3693 /// a primary and secondary type descriptor. If the primary doesn't
3694 /// provide the needed information, the request is passed on to the
3697 private sealed class MergedTypeDescriptor
: ICustomTypeDescriptor
3699 private ICustomTypeDescriptor _primary
;
3700 private ICustomTypeDescriptor _secondary
;
3703 /// Creates a new MergedTypeDescriptor.
3705 internal MergedTypeDescriptor(ICustomTypeDescriptor primary
, ICustomTypeDescriptor secondary
)
3708 _secondary
= secondary
;
3712 /// ICustomTypeDescriptor implementation.
3714 AttributeCollection ICustomTypeDescriptor
.GetAttributes()
3716 AttributeCollection attrs
= _primary
.GetAttributes();
3719 attrs
= _secondary
.GetAttributes();
3722 Debug
.Assert(attrs
!= null, "Someone should have handled this");
3727 /// ICustomTypeDescriptor implementation.
3729 string ICustomTypeDescriptor
.GetClassName()
3731 string className
= _primary
.GetClassName();
3732 if (className
== null)
3734 className
= _secondary
.GetClassName();
3737 Debug
.Assert(className
!= null, "Someone should have handled this");
3742 /// ICustomTypeDescriptor implementation.
3744 string ICustomTypeDescriptor
.GetComponentName()
3746 string name
= _primary
.GetComponentName();
3749 name
= _secondary
.GetComponentName();
3756 /// ICustomTypeDescriptor implementation.
3758 TypeConverter ICustomTypeDescriptor
.GetConverter()
3760 TypeConverter converter
= _primary
.GetConverter();
3761 if (converter
== null)
3763 converter
= _secondary
.GetConverter();
3766 Debug
.Assert(converter
!= null, "Someone should have handled this");
3771 /// ICustomTypeDescriptor implementation.
3773 EventDescriptor ICustomTypeDescriptor
.GetDefaultEvent()
3775 EventDescriptor evt
= _primary
.GetDefaultEvent();
3778 evt
= _secondary
.GetDefaultEvent();
3785 /// ICustomTypeDescriptor implementation.
3787 PropertyDescriptor ICustomTypeDescriptor
.GetDefaultProperty()
3789 PropertyDescriptor prop
= _primary
.GetDefaultProperty();
3792 prop
= _secondary
.GetDefaultProperty();
3799 /// ICustomTypeDescriptor implementation.
3801 object ICustomTypeDescriptor
.GetEditor(Type editorBaseType
)
3803 if (editorBaseType
== null)
3805 throw new ArgumentNullException("editorBaseType");
3808 object editor
= _primary
.GetEditor(editorBaseType
);
3811 editor
= _secondary
.GetEditor(editorBaseType
);
3818 /// ICustomTypeDescriptor implementation.
3820 EventDescriptorCollection ICustomTypeDescriptor
.GetEvents()
3822 EventDescriptorCollection events
= _primary
.GetEvents();
3825 events
= _secondary
.GetEvents();
3828 Debug
.Assert(events
!= null, "Someone should have handled this");
3833 /// ICustomTypeDescriptor implementation.
3835 EventDescriptorCollection ICustomTypeDescriptor
.GetEvents(Attribute
[] attributes
)
3837 EventDescriptorCollection events
= _primary
.GetEvents(attributes
);
3840 events
= _secondary
.GetEvents(attributes
);
3843 Debug
.Assert(events
!= null, "Someone should have handled this");
3848 /// ICustomTypeDescriptor implementation.
3850 PropertyDescriptorCollection ICustomTypeDescriptor
.GetProperties()
3852 PropertyDescriptorCollection properties
= _primary
.GetProperties();
3853 if (properties
== null)
3855 properties
= _secondary
.GetProperties();
3858 Debug
.Assert(properties
!= null, "Someone should have handled this");
3863 /// ICustomTypeDescriptor implementation.
3865 PropertyDescriptorCollection ICustomTypeDescriptor
.GetProperties(Attribute
[] attributes
)
3867 PropertyDescriptorCollection properties
= _primary
.GetProperties(attributes
);
3868 if (properties
== null)
3870 properties
= _secondary
.GetProperties(attributes
);
3873 Debug
.Assert(properties
!= null, "Someone should have handled this");
3878 /// ICustomTypeDescriptor implementation.
3880 object ICustomTypeDescriptor
.GetPropertyOwner(PropertyDescriptor pd
)
3882 object owner
= _primary
.GetPropertyOwner(pd
);
3885 owner
= _secondary
.GetPropertyOwner(pd
);
3893 /// This is a linked list node that is comprised of a type
3894 /// description provider. Each node contains a Next pointer
3895 /// to the next node in the list and also a Provider pointer
3896 /// which contains the type description provider this node
3897 /// represents. The implementation of TypeDescriptionProvider
3898 /// that the node provides simply invokes the corresponding
3899 /// method on the node's provider.
3901 private sealed class TypeDescriptionNode
: TypeDescriptionProvider
3903 internal TypeDescriptionNode Next
;
3904 internal TypeDescriptionProvider Provider
;
3907 /// Creates a new type description node.
3909 internal TypeDescriptionNode(TypeDescriptionProvider provider
)
3911 Provider
= provider
;
3915 /// Implements CreateInstance. This just walks the linked list
3916 /// looking for someone who implements the call.
3918 public override object CreateInstance(IServiceProvider provider
, Type objectType
, Type
[] argTypes
, object[] args
)
3920 if (objectType
== null)
3922 throw new ArgumentNullException("objectType");
3925 if (argTypes
!= null)
3929 throw new ArgumentNullException("args");
3932 if (argTypes
.Length
!= args
.Length
)
3934 throw new ArgumentException(SR
.GetString(SR
.TypeDescriptorArgsCountMismatch
));
3938 return Provider
.CreateInstance(provider
, objectType
, argTypes
, args
);
3942 /// Implements GetCache. This just walks the linked
3943 /// list looking for someone who implements the call.
3945 public override IDictionary
GetCache(object instance
)
3947 if (instance
== null)
3949 throw new ArgumentNullException("instance");
3952 return Provider
.GetCache(instance
);
3956 /// Implements GetExtendedTypeDescriptor. This creates a custom type
3957 /// descriptor that walks the linked list for each of its calls.
3959 public override ICustomTypeDescriptor
GetExtendedTypeDescriptor(object instance
)
3961 if (instance
== null)
3963 throw new ArgumentNullException("instance");
3966 return new DefaultExtendedTypeDescriptor(this, instance
);
3969 protected internal override IExtenderProvider
[] GetExtenderProviders(object instance
)
3971 if (instance
== null)
3973 throw new ArgumentNullException("instance");
3976 return Provider
.GetExtenderProviders(instance
);
3980 /// The name of the specified component, or null if the component has no name.
3981 /// In many cases this will return the same value as GetComponentName. If the
3982 /// component resides in a nested container or has other nested semantics, it may
3983 /// return a different fully qualfied name.
3985 /// If not overridden, the default implementation of this method will call
3986 /// GetTypeDescriptor.GetComponentName.
3988 public override string GetFullComponentName(object component
)
3990 if (component
== null)
3992 throw new ArgumentNullException("component");
3995 return Provider
.GetFullComponentName(component
);
3999 /// Implements GetReflectionType. This just walks the linked list
4000 /// looking for someone who implements the call.
4002 public override Type
GetReflectionType(Type objectType
, object instance
)
4004 if (objectType
== null)
4006 throw new ArgumentNullException("objectType");
4009 return Provider
.GetReflectionType(objectType
, instance
);
4012 public override Type
GetRuntimeType(Type objectType
)
4014 if (objectType
== null)
4016 throw new ArgumentNullException("objectType");
4019 return Provider
.GetRuntimeType(objectType
);
4023 /// Implements GetTypeDescriptor. This creates a custom type
4024 /// descriptor that walks the linked list for each of its calls.
4027 [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")]
4028 public override ICustomTypeDescriptor
GetTypeDescriptor(Type objectType
, object instance
)
4030 if (objectType
== null)
4032 throw new ArgumentNullException("objectType");
4035 if (instance
!= null && !objectType
.IsInstanceOfType(instance
))
4037 throw new ArgumentException("instance");
4040 return new DefaultTypeDescriptor(this, objectType
, instance
);
4043 public override bool IsSupportedType(Type type
)
4047 throw new ArgumentNullException("type");
4049 return Provider
.IsSupportedType(type
);
4053 /// A type descriptor for extended types. This type descriptor
4054 /// looks at the head node in the linked list.
4056 private struct DefaultExtendedTypeDescriptor
: ICustomTypeDescriptor
4058 private TypeDescriptionNode _node
;
4059 private object _instance
;
4062 /// Creates a new WalkingExtendedTypeDescriptor.
4064 internal DefaultExtendedTypeDescriptor(TypeDescriptionNode node
, object instance
)
4067 _instance
= instance
;
4071 /// ICustomTypeDescriptor implementation.
4073 AttributeCollection ICustomTypeDescriptor
.GetAttributes()
4075 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4076 // If so, we can call on it directly rather than creating another
4077 // custom type descriptor
4079 TypeDescriptionProvider p
= _node
.Provider
;
4080 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4083 return rp
.GetExtendedAttributes(_instance
);
4086 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4087 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4088 AttributeCollection attrs
= desc
.GetAttributes();
4089 if (attrs
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetAttributes"));
4094 /// ICustomTypeDescriptor implementation.
4096 string ICustomTypeDescriptor
.GetClassName()
4098 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4099 // If so, we can call on it directly rather than creating another
4100 // custom type descriptor
4102 TypeDescriptionProvider p
= _node
.Provider
;
4103 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4106 return rp
.GetExtendedClassName(_instance
);
4109 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4110 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4111 string name
= desc
.GetClassName();
4112 if (name
== null) name
= _instance
.GetType().FullName
;
4117 /// ICustomTypeDescriptor implementation.
4119 string ICustomTypeDescriptor
.GetComponentName()
4121 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4122 // If so, we can call on it directly rather than creating another
4123 // custom type descriptor
4125 TypeDescriptionProvider p
= _node
.Provider
;
4126 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4129 return rp
.GetExtendedComponentName(_instance
);
4132 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4133 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4134 return desc
.GetComponentName();
4138 /// ICustomTypeDescriptor implementation.
4140 TypeConverter ICustomTypeDescriptor
.GetConverter()
4142 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4143 // If so, we can call on it directly rather than creating another
4144 // custom type descriptor
4146 TypeDescriptionProvider p
= _node
.Provider
;
4147 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4150 return rp
.GetExtendedConverter(_instance
);
4153 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4154 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4155 TypeConverter converter
= desc
.GetConverter();
4156 if (converter
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetConverter"));
4161 /// ICustomTypeDescriptor implementation.
4163 EventDescriptor ICustomTypeDescriptor
.GetDefaultEvent()
4165 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4166 // If so, we can call on it directly rather than creating another
4167 // custom type descriptor
4169 TypeDescriptionProvider p
= _node
.Provider
;
4170 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4173 return rp
.GetExtendedDefaultEvent(_instance
);
4176 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4177 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4178 return desc
.GetDefaultEvent();
4182 /// ICustomTypeDescriptor implementation.
4184 PropertyDescriptor ICustomTypeDescriptor
.GetDefaultProperty()
4186 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4187 // If so, we can call on it directly rather than creating another
4188 // custom type descriptor
4190 TypeDescriptionProvider p
= _node
.Provider
;
4191 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4194 return rp
.GetExtendedDefaultProperty(_instance
);
4197 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4198 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4199 return desc
.GetDefaultProperty();
4203 /// ICustomTypeDescriptor implementation.
4205 object ICustomTypeDescriptor
.GetEditor(Type editorBaseType
)
4207 if (editorBaseType
== null)
4209 throw new ArgumentNullException("editorBaseType");
4212 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4213 // If so, we can call on it directly rather than creating another
4214 // custom type descriptor
4216 TypeDescriptionProvider p
= _node
.Provider
;
4217 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4220 return rp
.GetExtendedEditor(_instance
, editorBaseType
);
4223 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4224 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4225 return desc
.GetEditor(editorBaseType
);
4229 /// ICustomTypeDescriptor implementation.
4231 EventDescriptorCollection ICustomTypeDescriptor
.GetEvents()
4233 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4234 // If so, we can call on it directly rather than creating another
4235 // custom type descriptor
4237 TypeDescriptionProvider p
= _node
.Provider
;
4238 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4241 return rp
.GetExtendedEvents(_instance
);
4244 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4245 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4246 EventDescriptorCollection events
= desc
.GetEvents();
4247 if (events
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetEvents"));
4252 /// ICustomTypeDescriptor implementation.
4254 EventDescriptorCollection ICustomTypeDescriptor
.GetEvents(Attribute
[] attributes
)
4256 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4257 // If so, we can call on it directly rather than creating another
4258 // custom type descriptor
4260 TypeDescriptionProvider p
= _node
.Provider
;
4261 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4264 // There is no need to filter these events. For extended objects, they
4265 // are accessed through our pipeline code, which always filters before
4266 // returning. So any filter we do here is redundant. Note that we do
4267 // pass a valid filter to a custom descriptor so it can optimize if it wants.
4268 EventDescriptorCollection events
= rp
.GetExtendedEvents(_instance
);
4272 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4273 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4274 EventDescriptorCollection evts
= desc
.GetEvents(attributes
);
4275 if (evts
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetEvents"));
4280 /// ICustomTypeDescriptor implementation.
4282 PropertyDescriptorCollection ICustomTypeDescriptor
.GetProperties()
4284 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4285 // If so, we can call on it directly rather than creating another
4286 // custom type descriptor
4288 TypeDescriptionProvider p
= _node
.Provider
;
4289 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4292 return rp
.GetExtendedProperties(_instance
);
4295 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4296 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4297 PropertyDescriptorCollection properties
= desc
.GetProperties();
4298 if (properties
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetProperties"));
4303 /// ICustomTypeDescriptor implementation.
4305 PropertyDescriptorCollection ICustomTypeDescriptor
.GetProperties(Attribute
[] attributes
)
4307 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4308 // If so, we can call on it directly rather than creating another
4309 // custom type descriptor
4311 TypeDescriptionProvider p
= _node
.Provider
;
4312 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4315 // There is no need to filter these properties. For extended objects, they
4316 // are accessed through our pipeline code, which always filters before
4317 // returning. So any filter we do here is redundant. Note that we do
4318 // pass a valid filter to a custom descriptor so it can optimize if it wants.
4319 PropertyDescriptorCollection props
= rp
.GetExtendedProperties(_instance
);
4323 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4324 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4325 PropertyDescriptorCollection properties
= desc
.GetProperties(attributes
);
4326 if (properties
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetProperties"));
4331 /// ICustomTypeDescriptor implementation.
4333 object ICustomTypeDescriptor
.GetPropertyOwner(PropertyDescriptor pd
)
4335 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4336 // If so, we can call on it directly rather than creating another
4337 // custom type descriptor
4339 TypeDescriptionProvider p
= _node
.Provider
;
4340 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4343 return rp
.GetExtendedPropertyOwner(_instance
, pd
);
4346 ICustomTypeDescriptor desc
= p
.GetExtendedTypeDescriptor(_instance
);
4347 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetExtendedTypeDescriptor"));
4348 object owner
= desc
.GetPropertyOwner(pd
);
4349 if (owner
== null) owner
= _instance
;
4355 /// The default type descriptor.
4357 private struct DefaultTypeDescriptor
: ICustomTypeDescriptor
4359 private TypeDescriptionNode _node
;
4360 private Type _objectType
;
4361 private object _instance
;
4364 /// Creates a new WalkingTypeDescriptor.
4366 internal DefaultTypeDescriptor(TypeDescriptionNode node
, Type objectType
, object instance
)
4369 _objectType
= objectType
;
4370 _instance
= instance
;
4374 /// ICustomTypeDescriptor implementation.
4376 AttributeCollection ICustomTypeDescriptor
.GetAttributes()
4378 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4379 // If so, we can call on it directly rather than creating another
4380 // custom type descriptor
4382 TypeDescriptionProvider p
= _node
.Provider
;
4383 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4384 AttributeCollection attrs
;
4387 attrs
= rp
.GetAttributes(_objectType
);
4390 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4391 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4392 attrs
= desc
.GetAttributes();
4393 if (attrs
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetAttributes"));
4400 /// ICustomTypeDescriptor implementation.
4402 string ICustomTypeDescriptor
.GetClassName()
4404 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4405 // If so, we can call on it directly rather than creating another
4406 // custom type descriptor
4408 TypeDescriptionProvider p
= _node
.Provider
;
4409 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4413 name
= rp
.GetClassName(_objectType
);
4416 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4417 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4418 name
= desc
.GetClassName();
4419 if (name
== null) name
= _objectType
.FullName
;
4426 /// ICustomTypeDescriptor implementation.
4428 string ICustomTypeDescriptor
.GetComponentName()
4430 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4431 // If so, we can call on it directly rather than creating another
4432 // custom type descriptor
4434 TypeDescriptionProvider p
= _node
.Provider
;
4435 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4439 name
= rp
.GetComponentName(_objectType
, _instance
);
4442 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4443 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4444 name
= desc
.GetComponentName();
4451 /// ICustomTypeDescriptor implementation.
4453 TypeConverter ICustomTypeDescriptor
.GetConverter()
4455 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4456 // If so, we can call on it directly rather than creating another
4457 // custom type descriptor
4459 TypeDescriptionProvider p
= _node
.Provider
;
4460 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4461 TypeConverter converter
;
4464 converter
= rp
.GetConverter(_objectType
, _instance
);
4467 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4468 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4469 converter
= desc
.GetConverter();
4470 if (converter
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetConverter"));
4477 /// ICustomTypeDescriptor implementation.
4479 EventDescriptor ICustomTypeDescriptor
.GetDefaultEvent()
4481 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4482 // If so, we can call on it directly rather than creating another
4483 // custom type descriptor
4485 TypeDescriptionProvider p
= _node
.Provider
;
4486 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4487 EventDescriptor defaultEvent
;
4490 defaultEvent
= rp
.GetDefaultEvent(_objectType
, _instance
);
4493 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4494 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4495 defaultEvent
= desc
.GetDefaultEvent();
4498 return defaultEvent
;
4502 /// ICustomTypeDescriptor implementation.
4504 PropertyDescriptor ICustomTypeDescriptor
.GetDefaultProperty()
4506 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4507 // If so, we can call on it directly rather than creating another
4508 // custom type descriptor
4510 TypeDescriptionProvider p
= _node
.Provider
;
4511 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4512 PropertyDescriptor defaultProperty
;
4515 defaultProperty
= rp
.GetDefaultProperty(_objectType
, _instance
);
4518 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4519 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4520 defaultProperty
= desc
.GetDefaultProperty();
4523 return defaultProperty
;
4527 /// ICustomTypeDescriptor implementation.
4529 object ICustomTypeDescriptor
.GetEditor(Type editorBaseType
)
4531 if (editorBaseType
== null)
4533 throw new ArgumentNullException("editorBaseType");
4536 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4537 // If so, we can call on it directly rather than creating another
4538 // custom type descriptor
4540 TypeDescriptionProvider p
= _node
.Provider
;
4541 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4545 editor
= rp
.GetEditor(_objectType
, _instance
, editorBaseType
);
4548 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4549 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4550 editor
= desc
.GetEditor(editorBaseType
);
4557 /// ICustomTypeDescriptor implementation.
4559 EventDescriptorCollection ICustomTypeDescriptor
.GetEvents()
4561 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4562 // If so, we can call on it directly rather than creating another
4563 // custom type descriptor
4565 TypeDescriptionProvider p
= _node
.Provider
;
4566 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4567 EventDescriptorCollection events
;
4570 events
= rp
.GetEvents(_objectType
);
4573 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4574 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4575 events
= desc
.GetEvents();
4576 if (events
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetEvents"));
4583 /// ICustomTypeDescriptor implementation.
4585 EventDescriptorCollection ICustomTypeDescriptor
.GetEvents(Attribute
[] attributes
)
4587 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4588 // If so, we can call on it directly rather than creating another
4589 // custom type descriptor
4591 TypeDescriptionProvider p
= _node
.Provider
;
4592 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4593 EventDescriptorCollection events
;
4596 events
= rp
.GetEvents(_objectType
);
4599 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4600 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4601 events
= desc
.GetEvents(attributes
);
4602 if (events
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetEvents"));
4609 /// ICustomTypeDescriptor implementation.
4611 PropertyDescriptorCollection ICustomTypeDescriptor
.GetProperties()
4613 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4614 // If so, we can call on it directly rather than creating another
4615 // custom type descriptor
4617 TypeDescriptionProvider p
= _node
.Provider
;
4618 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4619 PropertyDescriptorCollection properties
;
4622 properties
= rp
.GetProperties(_objectType
);
4625 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4626 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4627 properties
= desc
.GetProperties();
4628 if (properties
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetProperties"));
4635 /// ICustomTypeDescriptor implementation.
4637 PropertyDescriptorCollection ICustomTypeDescriptor
.GetProperties(Attribute
[] attributes
)
4639 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4640 // If so, we can call on it directly rather than creating another
4641 // custom type descriptor
4643 TypeDescriptionProvider p
= _node
.Provider
;
4644 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4645 PropertyDescriptorCollection properties
;
4648 properties
= rp
.GetProperties(_objectType
);
4651 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4652 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4653 properties
= desc
.GetProperties(attributes
);
4654 if (properties
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetProperties"));
4661 /// ICustomTypeDescriptor implementation.
4663 object ICustomTypeDescriptor
.GetPropertyOwner(PropertyDescriptor pd
)
4665 // Check to see if the provider we get is a ReflectTypeDescriptionProvider.
4666 // If so, we can call on it directly rather than creating another
4667 // custom type descriptor
4669 TypeDescriptionProvider p
= _node
.Provider
;
4670 ReflectTypeDescriptionProvider rp
= p
as ReflectTypeDescriptionProvider
;
4674 owner
= rp
.GetPropertyOwner(_objectType
, _instance
, pd
);
4677 ICustomTypeDescriptor desc
= p
.GetTypeDescriptor(_objectType
, _instance
);
4678 if (desc
== null) throw new InvalidOperationException(SR
.GetString(SR
.TypeDescriptorProviderError
, _node
.Provider
.GetType().FullName
, "GetTypeDescriptor"));
4679 owner
= desc
.GetPropertyOwner(pd
);
4680 if (owner
== null) owner
= _instance
;
4689 /// This is a simple internal type that allows external parties
4690 /// to public ina custom type description provider for COM
4693 [TypeDescriptionProvider("System.Windows.Forms.ComponentModel.Com2Interop.ComNativeDescriptor, " + AssemblyRef
.SystemWindowsForms
)]
4694 private sealed class TypeDescriptorComObject
4699 /// This is a simple internal type that allows external parties to
4700 /// register a custom type description provider for all interface types.
4702 private sealed class TypeDescriptorInterface