The Labs \ Source Viewer \ SSCLI \ System.ComponentModel \ DebugTypeDescriptor

  1. //------------------------------------------------------------------------------
  2. // <copyright file="DebugTypeDescriptor.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. #if DEBUG
  16. /*
  17.    
  18.     This class exists in debug only.  It is a complete copy of the
  19.     V1.0 TypeDescriptor object and is used to validate that the
  20.     behavior of the V2.0 TypeDescriptor matches 1.0 behavior.
  21.    
  22. */
  23. namespace System.ComponentModel
  24. {
  25.     using System.Runtime.Serialization.Formatters;
  26.     using System.Threading;
  27.     using System.Runtime.Remoting.Activation;
  28.     using System.Runtime.InteropServices;
  29.     using System.Diagnostics;
  30.     using System.Diagnostics.CodeAnalysis;
  31.     using System;
  32.     using CodeAccessPermission = System.Security.CodeAccessPermission;
  33.     using System.Security.Permissions;
  34.     using System.Collections;
  35.     using System.Globalization;
  36.     using System.IO;
  37.     using System.Reflection;
  38.     using Microsoft.Win32;
  39.     using System.ComponentModel.Design;
  40.    
  41.     /// <devdoc>
  42.     /// <para>Provides information about the properties and events
  43.     /// for a component. This class cannot be inherited.</para>
  44.     /// </devdoc>
  45.     [HostProtection(SharedState = true)]
  46.     internal sealed class DebugTypeDescriptor
  47.     {
  48.         private static Hashtable cachedComponentEntries = new Hashtable();
  49.         private static Hashtable editorTables = new Hashtable();
  50.         private static Hashtable attributeCache = new Hashtable();
  51.         private static RefreshEventHandler refreshHandler = null;
  52.         #pragma warning disable 618
  53.         private static IComNativeDescriptorHandler comNativeDescriptorHandler = null;
  54.         #pragma warning restore 618
  55.         private static TraceSwitch CompDescrSwitch = new TraceSwitch("CompDescr", "Debug DebugTypeDescriptor.");
  56.        
  57.         private DebugTypeDescriptor()
  58.         {
  59.         }
  60.        
  61.         private static ComponentEntry GetEntry(object component, Type componentType)
  62.         {
  63.             ComponentEntry entry = null;
  64.            
  65.             lock (cachedComponentEntries) {
  66.                 entry = (ComponentEntry)cachedComponentEntries[componentType];
  67.                 if (entry == null) {
  68.                     entry = new ComponentEntry(componentType);
  69.                     cachedComponentEntries[componentType] = entry;
  70.                 }
  71.             }
  72.            
  73.             return entry;
  74.         }
  75.        
  76.         /// <internalonly/>
  77.         /// <devdoc>
  78.         /// </devdoc>
  79.         #pragma warning disable 618
  80.         public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
  81.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  82.             get { return comNativeDescriptorHandler; }
  83.             [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
  84.             set { comNativeDescriptorHandler = value; }
  85.         }
  86.         #pragma warning restore 618
  87.        
  88.         /// <devdoc>
  89.         /// <para>Occurs when Refreshed is raised for a component.</para>
  90.         /// </devdoc>
  91.         public static event RefreshEventHandler Refreshed {
  92.             add { refreshHandler += value; }
  93.             remove { refreshHandler -= value; }
  94.         }
  95.        
  96.         /// <internalonly/>
  97.         /// <devdoc>
  98.         /// <para>Adds an editor table for the given editor base type.
  99.         /// Typically, editors are specified as metadata on an object. If no metadata for a
  100.         /// requested editor base type can be found on an object, however, the
  101.         /// DebugTypeDescriptor will search an editor
  102.         /// table for the editor type, if one can be found.</para>
  103.         /// </devdoc>
  104.         public static void AddEditorTable(Type editorBaseType, Hashtable table)
  105.         {
  106.             lock (editorTables) {
  107.                 if (!editorTables.ContainsKey(editorBaseType)) {
  108.                     editorTables[editorBaseType] = table;
  109.                 }
  110.             }
  111.         }
  112.        
  113.         /// <devdoc>
  114.         /// <para>
  115.         /// Creates an instance of the designer associated with the
  116.         /// specified <paramref name="component"/>.
  117.         /// </para>
  118.         /// </devdoc>
  119.         public static IDesigner CreateDesigner(IComponent component, Type designerBaseType)
  120.         {
  121.             Type designerType = null;
  122.             IDesigner designer = null;
  123.            
  124.             Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "CreateDesigner(" + component.GetType().FullName + ")");
  125.            
  126.             // Get the set of attributes for this type
  127.             //
  128.             AttributeCollection attributes = GetAttributes(component);
  129.            
  130.             for (int i = 0; i < attributes.Count; i++) {
  131.                 if (attributes[i] is DesignerAttribute) {
  132.                     DesignerAttribute da = (DesignerAttribute)attributes[i];
  133.                     Type attributeBaseType = Type.GetType(da.DesignerBaseTypeName);
  134.                     if (attributeBaseType != null && attributeBaseType == designerBaseType) {
  135.                         ISite site = component.Site;
  136.                         bool foundService = false;
  137.                        
  138.                         if (site != null) {
  139.                             ITypeResolutionService tr = (ITypeResolutionService)site.GetService(typeof(ITypeResolutionService));
  140.                             if (tr != null) {
  141.                                 foundService = true;
  142.                                 designerType = tr.GetType(da.DesignerTypeName);
  143.                             }
  144.                         }
  145.                        
  146.                         if (!foundService) {
  147.                             designerType = Type.GetType(da.DesignerTypeName);
  148.                         }
  149.                        
  150.                         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 + "'");
  151.                         if (designerType != null) {
  152.                             break;
  153.                         }
  154.                     }
  155.                 }
  156.             }
  157.            
  158.             if (designerType != null) {
  159.                 designer = (IDesigner)Activator.CreateInstance(designerType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null);
  160.             }
  161.             else {
  162.                 Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "Could not find designer for: " + component.GetType().FullName);
  163.             }
  164.             return designer;
  165.         }
  166.        
  167.         /// <devdoc>
  168.         /// This dynamically binds an EventDescriptor to a type.
  169.         /// </devdoc>
  170.         [ReflectionPermission(SecurityAction.LinkDemand, Flags = ReflectionPermissionFlag.MemberAccess)]
  171.         public static EventDescriptor CreateEvent(Type componentType, string name, Type type, params Attribute[] attributes)
  172.         {
  173.             return new DebugReflectEventDescriptor(componentType, name, type, attributes);
  174.         }
  175.        
  176.         /// <devdoc>
  177.         /// This creates a new event descriptor identical to an existing event descriptor. The new event descriptor
  178.         /// has the specified metadata attributes merged with the existing metadata attributes.
  179.         /// </devdoc>
  180.         [ReflectionPermission(SecurityAction.LinkDemand, Flags = ReflectionPermissionFlag.MemberAccess)]
  181.         public static EventDescriptor CreateEvent(Type componentType, EventDescriptor oldEventDescriptor, params Attribute[] attributes)
  182.         {
  183.             return new DebugReflectEventDescriptor(componentType, oldEventDescriptor, attributes);
  184.         }
  185.        
  186.         /// <devdoc>
  187.         /// This dynamically binds a PropertyDescriptor to a type.
  188.         /// </devdoc>
  189.         [ReflectionPermission(SecurityAction.LinkDemand, Flags = ReflectionPermissionFlag.MemberAccess)]
  190.         public static PropertyDescriptor CreateProperty(Type componentType, string name, Type type, params Attribute[] attributes)
  191.         {
  192.             return new DebugReflectPropertyDescriptor(componentType, name, type, attributes);
  193.         }
  194.        
  195.         /// <devdoc>
  196.         /// This creates a new property descriptor identical to an existing property descriptor. The new property descriptor
  197.         /// has the specified metadata attributes merged with the existing metadata attributes.
  198.         /// </devdoc>
  199.         [ReflectionPermission(SecurityAction.LinkDemand, Flags = ReflectionPermissionFlag.MemberAccess)]
  200.         public static PropertyDescriptor CreateProperty(Type componentType, PropertyDescriptor oldPropertyDescriptor, params Attribute[] attributes)
  201.         {
  202.            
  203.             // We must do some special case work here for extended properties. If the old property descriptor is really
  204.             // an extender property that is being surfaced on a component as a normal property, then we must
  205.             // do work here or else DebugReflectPropertyDescriptor will fail to resolve the get and set methods. We check
  206.             // for the necessary ExtenderProvidedPropertyAttribute and if we find it, we create an
  207.             // ExtendedPropertyDescriptor instead. We only do this if the component class is the same, since the user
  208.             // may want to re-route the property to a different target.
  209.             //
  210.             if (componentType == oldPropertyDescriptor.ComponentType) {
  211.                 ExtenderProvidedPropertyAttribute attr = (ExtenderProvidedPropertyAttribute)oldPropertyDescriptor.Attributes[typeof(ExtenderProvidedPropertyAttribute)];
  212.                
  213.                 if (attr.ExtenderProperty != null) {
  214.                     return new DebugExtendedPropertyDescriptor((DebugReflectPropertyDescriptor)attr.ExtenderProperty, attr.ReceiverType, attr.Provider, attributes);
  215.                 }
  216.             }
  217.            
  218.             // This is either a normal prop or the caller has changed target classes.
  219.             //
  220.             return new DebugReflectPropertyDescriptor(componentType, oldPropertyDescriptor, attributes);
  221.         }
  222.        
  223.         /// <devdoc>
  224.         /// <para>
  225.         /// Gets a
  226.         /// collection of attributes for the specified type of component.
  227.         /// </para>
  228.         /// </devdoc>
  229.         public static AttributeCollection GetAttributes(Type componentType)
  230.         {
  231.             return GetEntry(null, componentType).GetAttributes(null);
  232.         }
  233.        
  234.         /// <devdoc>
  235.         /// <para>
  236.         /// Gets a collection of attributes for the specified
  237.         /// <paramref name="component"/>.
  238.         /// </para>
  239.         /// </devdoc>
  240.         public static AttributeCollection GetAttributes(object component)
  241.         {
  242.             return GetAttributes(component, false);
  243.         }
  244.        
  245.         /// <devdoc>
  246.         /// <para>
  247.         /// Gets a collection of attributes for the specified
  248.         /// <paramref name="component"/>.
  249.         /// </para>
  250.         /// </devdoc>
  251.         public static AttributeCollection GetAttributes(object component, bool noCustomTypeDesc)
  252.         {
  253.             if (component == null) {
  254.                 return new AttributeCollection((Attribute[])null);
  255.             }
  256.            
  257.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  258.                
  259.                 // Do not rip this varible -- it is here to make the get to
  260.                 // this static variable thread-safe.
  261.                 //
  262.                 #pragma warning disable 618
  263.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  264.                 #pragma warning restore 618
  265.                
  266.                 if (handler != null) {
  267.                     return handler.GetAttributes(component);
  268.                 }
  269.                 return new AttributeCollection((Attribute[])null);
  270.             }
  271.            
  272.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  273.                 return ((ICustomTypeDescriptor)component).GetAttributes();
  274.             }
  275.            
  276.             return GetEntry(component, component.GetType()).GetAttributes(component);
  277.         }
  278.        
  279.        
  280.         /// <devdoc>
  281.         /// <para>
  282.         /// Gets the name of the class for the specified
  283.         /// <paramref name="component"/>.
  284.         /// </para>
  285.         /// </devdoc>
  286.         public static string GetClassName(object component)
  287.         {
  288.             return GetClassName(component, false);
  289.         }
  290.        
  291.         /// <devdoc>
  292.         /// <para>
  293.         /// Gets the name of the class for the specified
  294.         /// <paramref name="component "/>using the custom type descriptor when <paramref name="noCustomTypeDesc
  295.         /// "/>
  296.         /// is <see langword='false'/>.
  297.         /// </para>
  298.         /// </devdoc>
  299.         public static string GetClassName(object component, bool noCustomTypeDesc)
  300.         {
  301.            
  302.             if (component == null) {
  303.                 throw new ArgumentNullException("component");
  304.             }
  305.            
  306.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  307.                
  308.                 // Do not rip this varible -- it is here to make the get to
  309.                 // this static variable thread-safe.
  310.                 //
  311.                 #pragma warning disable 618
  312.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  313.                 #pragma warning restore 618
  314.                 if (handler != null) {
  315.                     return handler.GetClassName(component);
  316.                 }
  317.             }
  318.            
  319.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  320.                 string str = ((ICustomTypeDescriptor)component).GetClassName();
  321.                 if (str != null) {
  322.                     return str;
  323.                 }
  324.             }
  325.            
  326.             return component.GetType().FullName;
  327.         }
  328.        
  329.        
  330.         /// <devdoc>
  331.         /// <para>
  332.         /// The name of the class for the specified <paramref name="component"/>.
  333.         /// </para>
  334.         /// </devdoc>
  335.         public static string GetComponentName(object component)
  336.         {
  337.             return GetComponentName(component, false);
  338.         }
  339.        
  340.         /// <devdoc>
  341.         /// <para>Gets the name of the class for the specified component.</para>
  342.         /// </devdoc>
  343.         public static string GetComponentName(object component, bool noCustomTypeDesc)
  344.         {
  345.            
  346.             if (component == null) {
  347.                 throw new ArgumentNullException("component");
  348.             }
  349.            
  350.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  351.                
  352.                 // Do not rip this varible -- it is here to make the get to
  353.                 // this static variable thread-safe.
  354.                 //
  355.                 #pragma warning disable 618
  356.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  357.                 #pragma warning restore 618
  358.                
  359.                 if (handler != null) {
  360.                     return handler.GetName(component);
  361.                 }
  362.             }
  363.            
  364.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  365.                 string str = ((ICustomTypeDescriptor)component).GetComponentName();
  366.                 if (str != null) {
  367.                     return str;
  368.                 }
  369.             }
  370.            
  371.             if (component is IComponent) {
  372.                 ISite site = ((IComponent)component).Site;
  373.                 if (site != null) {
  374.                     return site.Name;
  375.                 }
  376.             }
  377.             return component.GetType().Name;
  378.         }
  379.        
  380.         /// <devdoc>
  381.         /// <para>Gets a type converter for the type of the specified
  382.         /// component.</para>
  383.         /// </devdoc>
  384.         public static TypeConverter GetConverter(object component)
  385.         {
  386.             return GetConverter(component, false);
  387.         }
  388.        
  389.         /// <devdoc>
  390.         /// <para>Gets a type converter for the type of the specified
  391.         /// component.</para>
  392.         /// </devdoc>
  393.         public static TypeConverter GetConverter(object component, bool noCustomTypeDesc)
  394.         {
  395.             if (component == null) {
  396.                 throw new ArgumentNullException("component");
  397.             }
  398.            
  399.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  400.                
  401.                 // Do not rip this varible -- it is here to make the get to
  402.                 // this static variable thread-safe.
  403.                 //
  404.                 #pragma warning disable 618
  405.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  406.                 #pragma warning restore 618
  407.                
  408.                 if (handler != null) {
  409.                     return handler.GetConverter(component);
  410.                 }
  411.                 return null;
  412.             }
  413.            
  414.             TypeConverter converter = null;
  415.            
  416.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  417.                 converter = ((ICustomTypeDescriptor)component).GetConverter();
  418.             }
  419.            
  420.             if (converter == null) {
  421.                 converter = GetEntry(component, component.GetType()).GetConverter(component);
  422.             }
  423.            
  424.             return converter;
  425.         }
  426.        
  427.         /// <devdoc>
  428.         /// <para>Gets a type converter for the specified type.</para>
  429.         /// </devdoc>
  430.         public static TypeConverter GetConverter(Type type)
  431.         {
  432.             return GetEntry(null, type).GetConverter();
  433.         }
  434.        
  435.         /// <devdoc>
  436.         /// Querying custom attributes is very expensive, so we cache them
  437.         /// here.
  438.         /// </devdoc>
  439.         static internal object[] GetCustomAttributes(Type type)
  440.         {
  441.             object[] attributes = (object[])attributeCache[type];
  442.             if (attributes == null) {
  443.                 attributes = type.GetCustomAttributes(false);
  444.                
  445.                 lock (attributeCache) {
  446.                     attributeCache[type] = attributes;
  447.                 }
  448.             }
  449.            
  450.             return attributes;
  451.         }
  452.        
  453.         /// <devdoc>
  454.         /// Querying custom attributes is very expensive, so we cache them
  455.         /// here.
  456.         /// </devdoc>
  457.         static internal object[] GetCustomAttributes(MemberInfo info)
  458.         {
  459.             object[] attributes = (object[])attributeCache[info];
  460.             if (attributes == null) {
  461.                 attributes = info.GetCustomAttributes(false);
  462.                
  463.                 lock (attributeCache) {
  464.                     attributeCache[info] = attributes;
  465.                 }
  466.             }
  467.            
  468.             return attributes;
  469.         }
  470.        
  471.         /// <devdoc>
  472.         /// <para>
  473.         /// Gets
  474.         /// the default event for the specified
  475.         /// type of component.
  476.         /// </para>
  477.         /// </devdoc>
  478.         public static EventDescriptor GetDefaultEvent(Type componentType)
  479.         {
  480.             return GetEntry(null, componentType).GetDefaultEvent(null);
  481.         }
  482.        
  483.         /// <devdoc>
  484.         /// <para>
  485.         /// Gets the default event for the specified
  486.         /// <paramref name="component"/>.
  487.         /// </para>
  488.         /// </devdoc>
  489.         public static EventDescriptor GetDefaultEvent(object component)
  490.         {
  491.             return GetDefaultEvent(component, false);
  492.         }
  493.        
  494.         /// <devdoc>
  495.         /// <para>
  496.         /// Gets the default event for a component.
  497.         /// </para>
  498.         /// </devdoc>
  499.         public static EventDescriptor GetDefaultEvent(object component, bool noCustomTypeDesc)
  500.         {
  501.             if (component == null) {
  502.                 return null;
  503.             }
  504.            
  505.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  506.                
  507.                 // Do not rip this varible -- it is here to make the get to
  508.                 // this static variable thread-safe.
  509.                 //
  510.                 #pragma warning disable 618
  511.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  512.                 #pragma warning disable 618
  513.                 if (handler != null) {
  514.                     return handler.GetDefaultEvent(component);
  515.                 }
  516.                 return null;
  517.             }
  518.            
  519.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  520.                 return ((ICustomTypeDescriptor)component).GetDefaultEvent();
  521.             }
  522.            
  523.             return GetEntry(component, component.GetType()).GetDefaultEvent(component);
  524.         }
  525.        
  526.         /// <devdoc>
  527.         /// <para>
  528.         /// Gets the default
  529.         /// property for the
  530.         /// specified type of component.
  531.         /// </para>
  532.         /// </devdoc>
  533.         public static PropertyDescriptor GetDefaultProperty(Type componentType)
  534.         {
  535.             return GetEntry(null, componentType).GetDefaultProperty(null);
  536.         }
  537.        
  538.         /// <devdoc>
  539.         /// <para>
  540.         /// Gets the default property for the specified
  541.         /// <paramref name="component"/>.
  542.         /// </para>
  543.         /// </devdoc>
  544.         public static PropertyDescriptor GetDefaultProperty(object component)
  545.         {
  546.             return GetDefaultProperty(component, false);
  547.         }
  548.        
  549.         /// <devdoc>
  550.         /// <para>
  551.         /// Gets the default property for the specified
  552.         /// <paramref name="component"/>.
  553.         /// </para>
  554.         /// </devdoc>
  555.         public static PropertyDescriptor GetDefaultProperty(object component, bool noCustomTypeDesc)
  556.         {
  557.             if (component == null) {
  558.                 return null;
  559.             }
  560.            
  561.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  562.                
  563.                 // Do not rip this varible -- it is here to make the get to
  564.                 // this static variable thread-safe.
  565.                 //
  566.                 #pragma warning disable 618
  567.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  568.                 #pragma warning restore 618
  569.                 if (handler != null) {
  570.                     return handler.GetDefaultProperty(component);
  571.                 }
  572.                 return null;
  573.             }
  574.            
  575.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  576.                 return ((ICustomTypeDescriptor)component).GetDefaultProperty();
  577.             }
  578.            
  579.             return GetEntry(component, component.GetType()).GetDefaultProperty(component);
  580.         }
  581.        
  582.         /// <devdoc>
  583.         /// <para>
  584.         /// Gets an editor with the specified base type for the
  585.         /// specified <paramref name="component"/>.
  586.         /// </para>
  587.         /// </devdoc>
  588.         public static object GetEditor(object component, Type editorBaseType)
  589.         {
  590.             return GetEditor(component, editorBaseType, false);
  591.         }
  592.        
  593.         /// <devdoc>
  594.         /// <para>
  595.         /// Gets an editor with the specified base type for the
  596.         /// specified <paramref name="component"/>.
  597.         /// </para>
  598.         /// </devdoc>
  599.         public static object GetEditor(object component, Type editorBaseType, bool noCustomTypeDesc)
  600.         {
  601.             if (component == null) {
  602.                 throw new ArgumentNullException("component");
  603.             }
  604.            
  605.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  606.                
  607.                 // Do not rip this varible -- it is here to make the get to
  608.                 // this static variable thread-safe.
  609.                 //
  610.                 #pragma warning disable 618
  611.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  612.                 #pragma warning restore 618
  613.                 if (handler != null) {
  614.                     return handler.GetEditor(component, editorBaseType);
  615.                 }
  616.                 return null;
  617.             }
  618.            
  619.             object editor = null;
  620.            
  621.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  622.                 editor = ((ICustomTypeDescriptor)component).GetEditor(editorBaseType);
  623.             }
  624.            
  625.             if (editor == null) {
  626.                 editor = GetEntry(component, component.GetType()).GetEditor(component, editorBaseType);
  627.             }
  628.            
  629.             return editor;
  630.         }
  631.        
  632.         /// <devdoc>
  633.         /// <para>Gets an editor with the specified base type for the specified type.</para>
  634.         /// </devdoc>
  635.         public static object GetEditor(Type type, Type editorBaseType)
  636.         {
  637.             Debug.Assert(type != null, "Can't get editor for null type");
  638.             return GetEntry(null, type).GetEditor(editorBaseType);
  639.         }
  640.        
  641.         /// <devdoc>
  642.         /// Retrieves a default editor table for the given editor base type.
  643.         /// </devdoc>
  644.         private static Hashtable GetEditorTable(Type editorBaseType)
  645.         {
  646.             object table = null;
  647.            
  648.             lock (editorTables) {
  649.                 table = editorTables[editorBaseType];
  650.             }
  651.            
  652.             if (table == null) {
  653.                 // Before we give up, it is possible that the
  654.                 // class initializer for editorBaseType hasn't
  655.                 // actually run. Force it now. We try/catch
  656.                 // here in case editorBaseType throws us a curve ball.
  657.                 //
  658.                 if (!editorBaseType.IsAbstract) {
  659.                     try {
  660.                         object o = Activator.CreateInstance(editorBaseType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null);
  661.                     }
  662.                     catch {
  663.                     }
  664.                 }
  665.                
  666.                 lock (editorTables) {
  667.                     table = editorTables[editorBaseType];
  668.                    
  669.                     // If the table is still null, then throw a
  670.                     // sentinel in there so we don't
  671.                     // go through this again.
  672.                     //
  673.                     if (table == null) {
  674.                         editorTables[editorBaseType] = editorTables;
  675.                     }
  676.                 }
  677.             }
  678.            
  679.             // Look for our sentinel value that indicates
  680.             // we have already tried and failed to get
  681.             // a table.
  682.             //
  683.             if (table == editorTables) {
  684.                 table = null;
  685.             }
  686.            
  687.             return (Hashtable)table;
  688.         }
  689.        
  690.         /// <devdoc>
  691.         /// <para>
  692.         /// Gets a collection of events for a specified type of component.
  693.         /// </para>
  694.         /// </devdoc>
  695.         public static EventDescriptorCollection GetEvents(Type componentType)
  696.         {
  697.             return GetEvents(componentType, null);
  698.         }
  699.        
  700.         /// <devdoc>
  701.         /// <para>
  702.         /// Gets a collection of events for a
  703.         /// specified <paramref name="component"/>.
  704.         /// </para>
  705.         /// </devdoc>
  706.         public static EventDescriptorCollection GetEvents(object component)
  707.         {
  708.             return GetEvents(component, false);
  709.         }
  710.        
  711.         /// <devdoc>
  712.         /// <para>
  713.         /// Gets a collection of events for a
  714.         /// specified <paramref name="component"/>.
  715.         /// </para>
  716.         /// </devdoc>
  717.         public static EventDescriptorCollection GetEvents(object component, bool noCustomTypeDesc)
  718.         {
  719.             if (component == null) {
  720.                 return new EventDescriptorCollection(null, true);
  721.             }
  722.            
  723.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  724.                
  725.                 // Do not rip this varible -- it is here to make the get to
  726.                 // this static variable thread-safe.
  727.                 //
  728.                 #pragma warning disable 618
  729.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  730.                 #pragma warning restore 618
  731.                 if (handler != null) {
  732.                     return handler.GetEvents(component);
  733.                 }
  734.                 return new EventDescriptorCollection(null, true);
  735.             }
  736.            
  737.            
  738.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  739.                 EventDescriptorCollection events = ((ICustomTypeDescriptor)component).GetEvents();
  740.                 return GetEntry(component, component.GetType()).FilterEvents(component, null, events);
  741.             }
  742.            
  743.             return GetEvents(component, null);
  744.         }
  745.        
  746.         /// <devdoc>
  747.         /// <para>
  748.         /// Gets a collection of events for a specified type of
  749.         /// component using a specified array of <paramref name="attributes "/>
  750.         /// as a filter.
  751.         /// </para>
  752.         /// </devdoc>
  753.         public static EventDescriptorCollection GetEvents(Type componentType, Attribute[] attributes)
  754.         {
  755.             return GetEntry(null, componentType).GetEvents(null, attributes);
  756.         }
  757.        
  758.         /// <devdoc>
  759.         /// <para>
  760.         /// Gets a collection of events for a
  761.         /// specified <paramref name="component "/>using a specified array of <paramref name="attributes"/>
  762.         /// as a filter.
  763.         /// </para>
  764.         /// </devdoc>
  765.         public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes)
  766.         {
  767.             return GetEvents(component, attributes, false);
  768.         }
  769.        
  770.         /// <devdoc>
  771.         /// <para>
  772.         /// Gets a collection of events for a
  773.         /// specified <paramref name="component "/>using a specified array of <paramref name="attributes
  774.         /// "/>
  775.         /// as a filter.
  776.         /// </para>
  777.         /// </devdoc>
  778.         public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes, bool noCustomTypeDesc)
  779.         {
  780.             if (component == null) {
  781.                 return new EventDescriptorCollection(null, true);
  782.             }
  783.            
  784.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  785.                
  786.                 // Do not rip this varible -- it is here to make the get to
  787.                 // this static variable thread-safe.
  788.                 //
  789.                 #pragma warning disable 618
  790.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  791.                 #pragma warning restore 618
  792.                
  793.                 if (handler != null) {
  794.                     return handler.GetEvents(component, attributes);
  795.                 }
  796.                 return new EventDescriptorCollection(null, true);
  797.             }
  798.            
  799.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  800.                 EventDescriptorCollection events = ((ICustomTypeDescriptor)component).GetEvents(attributes);
  801.                 return GetEntry(component, component.GetType()).FilterEvents(component, attributes, events);
  802.             }
  803.            
  804.             return GetEntry(component, component.GetType()).GetEvents(component, attributes, (component is ICustomTypeDescriptor));
  805.         }
  806.        
  807.         /// <devdoc>
  808.         /// <para>
  809.         /// Gets a collection of properties for a specified type of
  810.         /// component.
  811.         /// </para>
  812.         /// </devdoc>
  813.         public static PropertyDescriptorCollection GetProperties(Type componentType)
  814.         {
  815.             return GetProperties(componentType, null);
  816.         }
  817.        
  818.         /// <devdoc>
  819.         /// <para>Gets a collection of properties for a specified
  820.         /// component.</para>
  821.         /// </devdoc>
  822.         public static PropertyDescriptorCollection GetProperties(object component)
  823.         {
  824.             return GetProperties(component, false);
  825.         }
  826.        
  827.         /// <devdoc>
  828.         /// <para>
  829.         /// Gets a collection of properties for a
  830.         /// specified <paramref name="component"/>.
  831.         /// </para>
  832.         /// </devdoc>
  833.         public static PropertyDescriptorCollection GetProperties(object component, bool noCustomTypeDesc)
  834.         {
  835.             if (component == null) {
  836.                 throw new ArgumentNullException("component");
  837.             }
  838.            
  839.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  840.                 PropertyDescriptorCollection properties = ((ICustomTypeDescriptor)component).GetProperties();
  841.                 return GetEntry(component, component.GetType()).FilterProperties(component, null, properties);
  842.             }
  843.            
  844.             return GetProperties(component, null, (component is ICustomTypeDescriptor));
  845.         }
  846.        
  847.         /// <devdoc>
  848.         /// <para>Gets a collection of properties for a specified type of
  849.         /// component using a specified array of attributes as a filter.</para>
  850.         /// </devdoc>
  851.         public static PropertyDescriptorCollection GetProperties(Type componentType, Attribute[] attributes)
  852.         {
  853.             return GetEntry(null, componentType).GetProperties(null, attributes);
  854.         }
  855.        
  856.         /// <devdoc>
  857.         /// <para>Gets a collection of properties for a specified
  858.         /// component using a specified array of attributes
  859.         /// as a filter.</para>
  860.         /// </devdoc>
  861.         public static PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes)
  862.         {
  863.             if (component == null) {
  864.                 throw new ArgumentNullException("component");
  865.             }
  866.            
  867.             return GetProperties(component, attributes, false);
  868.         }
  869.        
  870.         /// <devdoc>
  871.         /// <para>Gets a collection of properties for a specified
  872.         /// component using a specified array of attributes
  873.         /// as a filter.</para>
  874.         /// </devdoc>
  875.         public static PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes, bool noCustomTypeDesc)
  876.         {
  877.             if (component == null) {
  878.                 return new PropertyDescriptorCollection(null, true);
  879.             }
  880.            
  881.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  882.                 // Do not rip this varible -- it is here to make the get to
  883.                 // this static variable thread-safe.
  884.                 //
  885.                 #pragma warning disable 618
  886.                 IComNativeDescriptorHandler handler = comNativeDescriptorHandler;
  887.                 #pragma warning restore 618
  888.                
  889.                 if (handler != null) {
  890.                     return handler.GetProperties(component, attributes);
  891.                 }
  892.                 return new PropertyDescriptorCollection(null, true);
  893.             }
  894.            
  895.             if (!noCustomTypeDesc && component is ICustomTypeDescriptor) {
  896.                 PropertyDescriptorCollection properties = ((ICustomTypeDescriptor)component).GetProperties(attributes);
  897.                 return GetEntry(component, component.GetType()).FilterProperties(component, attributes, properties);
  898.             }
  899.            
  900.             return GetEntry(component, component.GetType()).GetProperties(component, attributes, (component is ICustomTypeDescriptor));
  901.         }
  902.        
  903.         /// <devdoc>
  904.         /// <para>Clears the properties and events for the specified
  905.         /// component from the
  906.         /// cache.</para>
  907.         /// </devdoc>
  908.         public static void Refresh(object component)
  909.         {
  910.            
  911.             if (component == null) {
  912.                 return;
  913.             }
  914.            
  915.             // COM objects aren't cached since we don't
  916.             // want to be holding references to them.
  917.             if (System.Runtime.InteropServices.Marshal.IsComObject(component)) {
  918.                 return;
  919.             }
  920.            
  921.             // We only fire the change event if we have cached the componet.
  922.             // Since we will recreate the cache entry if anyone has asked for
  923.             // this component... this prevents getting tons of duplicate
  924.             // Refresh events.
  925.             //
  926.             ComponentEntry entry = null;
  927.            
  928.             lock (cachedComponentEntries) {
  929.                 entry = (ComponentEntry)cachedComponentEntries[component.GetType()];
  930.             }
  931.            
  932.             if (entry != null) {
  933.                
  934.                 // Clear the attribute cache. It's not that expensive to build
  935.                 // this back up if we need to.
  936.                 //
  937.                 lock (attributeCache) {
  938.                     attributeCache.Clear();
  939.                 }
  940.                
  941.                 // Remove the item from the cache, it will get recreated
  942.                 // on demand.
  943.                 //
  944.                 lock (cachedComponentEntries) {
  945.                     cachedComponentEntries.Remove(component.GetType());
  946.                 }
  947.                
  948.                 // Allow the entry to dispose itself.
  949.                 //
  950.                 entry.Dispose(component);
  951.                
  952.                 // Notify listeners of the change
  953.                 //
  954.                 RefreshEventHandler handler = refreshHandler;
  955.                
  956.                 if (handler != null) {
  957.                     handler(new RefreshEventArgs(component));
  958.                 }
  959.             }
  960.         }
  961.        
  962.         /// <devdoc>
  963.         /// <para>Clears the properties and events for the specified type
  964.         /// of component from the
  965.         /// cache.</para>
  966.         /// </devdoc>
  967.         public static void Refresh(Type type)
  968.         {
  969.            
  970.             if (type == null) {
  971.                 return;
  972.             }
  973.            
  974.             // We only fire the change event if we have cached the componet.
  975.             // Since we will recreate the cache entry if anyone has asked for
  976.             // this component... this prevents getting tons of duplicate
  977.             // Refresh events.
  978.             //
  979.             bool found = false;
  980.            
  981.             lock (cachedComponentEntries) {
  982.                
  983.                 ArrayList removeItems = null;
  984.                
  985.                 // find all the instances of the requested type
  986.                 // and any types that derive from it,
  987.                 // and remove them.
  988.                 //
  989.                 foreach (Type cacheType in cachedComponentEntries.Keys) {
  990.                     if (type.IsAssignableFrom(cacheType)) {
  991.                         if (removeItems == null) {
  992.                             removeItems = new ArrayList();
  993.                         }
  994.                         removeItems.Add(cacheType);
  995.                     }
  996.                 }
  997.                
  998.                 if (removeItems != null) {
  999.                     foreach (Type t in removeItems) {
  1000.                         // Remove the item from the cache, it will get recreated
  1001.                         // on demand.
  1002.                         //
  1003.                         cachedComponentEntries.Remove(t);
  1004.                     }
  1005.                     found = true;
  1006.                 }
  1007.             }
  1008.            
  1009.             if (found) {
  1010.                
  1011.                 // Clear the attribute cache. It's not that expensive to build
  1012.                 // this back up if we need to.
  1013.                 //
  1014.                 lock (attributeCache) {
  1015.                     attributeCache.Clear();
  1016.                 }
  1017.                
  1018.                 RefreshEventHandler handler = refreshHandler;
  1019.                
  1020.                 // Notify listeners of the change
  1021.                 //
  1022.                 if (handler != null) {
  1023.                     handler(new RefreshEventArgs(type));
  1024.                 }
  1025.             }
  1026.         }
  1027.        
  1028.         /// <devdoc>
  1029.         /// <para>Clears the properties and events for the specified
  1030.         /// module from the
  1031.         /// cache.</para>
  1032.         /// </devdoc>
  1033.         public static void Refresh(Module module)
  1034.         {
  1035.            
  1036.             if (module == null) {
  1037.                 return;
  1038.             }
  1039.            
  1040.             ArrayList list = null;
  1041.            
  1042.             lock (cachedComponentEntries) {
  1043.                 foreach (Type curType in cachedComponentEntries.Keys) {
  1044.                     if (curType.Module.Equals(module)) {
  1045.                         if (list == null) {
  1046.                             list = new ArrayList();
  1047.                         }
  1048.                         list.Add(curType);
  1049.                     }
  1050.                 }
  1051.                
  1052.                 // now remove all the ones we tagged -- can't do this
  1053.                 // in the enumeration.
  1054.                 //
  1055.                 if (list != null) {
  1056.                     foreach (Type t in list) {
  1057.                         cachedComponentEntries.Remove(t);
  1058.                     }
  1059.                 }
  1060.             }
  1061.            
  1062.             if (list != null) {
  1063.                 // Clear the attribute cache. It's not that expensive to build
  1064.                 // this back up if we need to.
  1065.                 //
  1066.                 lock (attributeCache) {
  1067.                     attributeCache.Clear();
  1068.                 }
  1069.                
  1070.                 RefreshEventHandler handler = refreshHandler;
  1071.                 if (handler != null) {
  1072.                     foreach (Type curType in list) {
  1073.                         handler(new RefreshEventArgs(curType));
  1074.                     }
  1075.                 }
  1076.             }
  1077.         }
  1078.        
  1079.         /// <devdoc>
  1080.         /// <para>Clears the properties and events for the specified
  1081.         /// assembly from the
  1082.         /// cache.</para>
  1083.         /// </devdoc>
  1084.         public static void Refresh(Assembly assembly)
  1085.         {
  1086.            
  1087.             if (assembly == null) {
  1088.                 return;
  1089.             }
  1090.            
  1091.             foreach (Module mod in assembly.GetModules()) {
  1092.                 Refresh(mod);
  1093.             }
  1094.         }
  1095.        
  1096.         /// <devdoc>
  1097.         /// <para>
  1098.         /// Sorts descriptors by name of the descriptor.
  1099.         /// </para>
  1100.         /// </devdoc>
  1101.         public static void SortDescriptorArray(IList infos)
  1102.         {
  1103.             ArrayList.Adapter(infos).Sort(MemberDescriptorComparer.Instance);
  1104.         }
  1105.        
  1106.        
  1107.         /// <devdoc>
  1108.         /// ComponentEntry contains the properties, events, extenders, and attributes for
  1109.         /// a given type of component.
  1110.         /// </devdoc>
  1111.         private class ComponentEntry
  1112.         {
  1113.             private Type componentType;
  1114.             private PropertyDescriptorCollection properties;
  1115.             private EventDescriptorCollection events;
  1116.             private AttributeCollection attributes;
  1117.             private IList extenders;
  1118.             private Hashtable wrappedExtenderTable;
  1119.             private TypeConverter converter;
  1120.             private object[] editors;
  1121.             private Type[] editorTypes;
  1122.             private int editorCount;
  1123.            
  1124.             // This is an index that we use to create a unique name for a property in the
  1125.             // event of a name collision. The only time we should use this is when
  1126.             // a name collision happened on an extender property that has no site or
  1127.             // no name on its site. Should be very rare.
  1128.             private static int collisionIndex = 0;
  1129.            
  1130.             // This is the signature we look for when creating types that are generic, but
  1131.             // want to know what type they are dealing with. Enums are a good example of this;
  1132.             // there is one enum converter that can work with all enums, but it needs to know
  1133.             // the type of enum it is dealing with.
  1134.             //
  1135.             private static Type[] typeConstructor = new Type[] {typeof(Type)};
  1136.            
  1137.             // This is where we store the various converters, etc for the intrinsic types.
  1138.             //
  1139.             private static Hashtable intrinsicTypeConverters;
  1140.            
  1141.             // For converters, etc that are bound to class attribute data, rather than a class
  1142.             // type, we have special key sentinel values that we put into the hash table.
  1143.             //
  1144.             private static object intrinsicEnumKey = new object();
  1145.             private static object intrinsicReferenceKey = new object();
  1146.            
  1147.             /// <devdoc>
  1148.             /// Creates a new ComponentEntry. The ComponentManager should be the
  1149.             /// only component that creates this.
  1150.             /// </devdoc>
  1151.             /// <internalonly/>
  1152.             public ComponentEntry(Type componentType)
  1153.             {
  1154.                 this.componentType = componentType;
  1155.             }
  1156.            
  1157.             /// <devdoc>
  1158.             /// This is a table we create for intrinsic types.
  1159.             /// There should be entries here ONLY for intrinsic
  1160.             /// types, as all other types we should be able to
  1161.             /// add attributes directly as metadata.
  1162.             /// </devdoc>
  1163.             private static Hashtable IntrinsicTypeConverters {
  1164.                 get {
  1165.                     // It is not worth taking a lock for this -- worst case of a collision
  1166.                     // would build two tables, one that garbage collects very quickly.
  1167.                     //
  1168.                     if (intrinsicTypeConverters == null) {
  1169.                         Hashtable temp = new Hashtable();
  1170.                        
  1171.                         // Add the intrinsics
  1172.                         //
  1173.                         temp[typeof(bool)] = typeof(BooleanConverter);
  1174.                         temp[typeof(byte)] = typeof(ByteConverter);
  1175.                         temp[typeof(sbyte)] = typeof(SByteConverter);
  1176.                         temp[typeof(char)] = typeof(CharConverter);
  1177.                         temp[typeof(double)] = typeof(DoubleConverter);
  1178.                         temp[typeof(string)] = typeof(StringConverter);
  1179.                         temp[typeof(int)] = typeof(Int32Converter);
  1180.                         temp[typeof(short)] = typeof(Int16Converter);
  1181.                         temp[typeof(long)] = typeof(Int64Converter);
  1182.                         temp[typeof(float)] = typeof(SingleConverter);
  1183.                         temp[typeof(UInt16)] = typeof(UInt16Converter);
  1184.                         temp[typeof(UInt32)] = typeof(UInt32Converter);
  1185.                         temp[typeof(UInt64)] = typeof(UInt64Converter);
  1186.                         temp[typeof(object)] = typeof(TypeConverter);
  1187.                         temp[typeof(void)] = typeof(TypeConverter);
  1188.                         temp[typeof(CultureInfo)] = typeof(CultureInfoConverter);
  1189.                         temp[typeof(DateTime)] = typeof(DateTimeConverter);
  1190.                         temp[typeof(decimal)] = typeof(DecimalConverter);
  1191.                         temp[typeof(TimeSpan)] = typeof(TimeSpanConverter);
  1192.                         temp[typeof(Guid)] = typeof(GuidConverter);
  1193.                         temp[typeof(Array)] = typeof(ArrayConverter);
  1194.                         temp[typeof(ICollection)] = typeof(CollectionConverter);
  1195.                        
  1196.                         // Special cases for things that are not bound to a specific type
  1197.                         //
  1198.                         temp[intrinsicEnumKey] = typeof(EnumConverter);
  1199.                         temp[intrinsicReferenceKey] = typeof(ReferenceConverter);
  1200.                        
  1201.                         intrinsicTypeConverters = temp;
  1202.                     }
  1203.                     return intrinsicTypeConverters;
  1204.                 }
  1205.             }
  1206.            
  1207.             /// <devdoc>
  1208.             /// Creates an instance of the requested type. This is used by converters
  1209.             /// and editors to create versions of those objects. CreateInstance
  1210.             /// will look for a constructor that takes a type. If one is found, the type of the
  1211.             /// component this entry is providing information for will be passed in. This allows
  1212.             /// a single object to be re-used for more than one type.
  1213.             /// </devdoc>
  1214.             private object CreateInstance(Type type)
  1215.             {
  1216.                 if ((!(type.IsPublic || type.IsNestedPublic)) && (type.Assembly == typeof(DebugTypeDescriptor).Assembly)) {
  1217.                     IntSecurity.FullReflection.Demand();
  1218.                 }
  1219.                
  1220.                 ConstructorInfo ctor = type.GetConstructor(typeConstructor);
  1221.                 if (ctor != null) {
  1222.                     return ctor.Invoke(new object[] {componentType});
  1223.                 }
  1224.                
  1225.                 return Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance, null, null, null);
  1226.             }
  1227.            
  1228.             // <doc>
  1229.             // <desc>
  1230.             // Disposes this entry. The work we do here is to make sure that
  1231.             // any cached information we saved on the given component has been
  1232.             // cleared out.
  1233.             // </desc>
  1234.             // <param term='component'>
  1235.             // The object to clear.
  1236.             // </param>
  1237.             // </doc>
  1238.             public void Dispose(object component)
  1239.             {
  1240.                 if (component is IComponent) {
  1241.                     IDictionaryService ds = (IDictionaryService)GetService((IComponent)component, typeof(IDictionaryService));
  1242.                     if (ds != null) {
  1243.                         ds.SetValue(typeof(AttributeCollection), null);
  1244.                         ds.SetValue(typeof(EventDescriptorCollection), null);
  1245.                         ds.SetValue(typeof(PropertyStash), null);
  1246.                     }
  1247.                 }
  1248.             }
  1249.            
  1250.             /// <devdoc>
  1251.             /// This function will pass through the set of members and select only those which match
  1252.             /// all of the given attributes.
  1253.             /// </devdoc>
  1254.             public virtual void FilterMembers(Type infoType, IList infos, Attribute[] attributes)
  1255.             {
  1256.                 if (attributes != null && attributes.Length > 0 && infos.Count > 0) {
  1257.                    
  1258.                     switch (attributes.Length) {
  1259.                         case 1:
  1260.                            
  1261.                             {
  1262.                                 Attribute filterAttribute = attributes[0];
  1263.                                 for (int i = infos.Count - 1; i >= 0; i--) {
  1264.                                     if (ShouldHideMember((MemberDescriptor)infos[i], filterAttribute)) {
  1265.                                         infos.RemoveAt(i);
  1266.                                     }
  1267.                                 }
  1268.                                 break;
  1269.                             }
  1270.                             break;
  1271.                         case 2:
  1272.                            
  1273.                             {
  1274.                                 Attribute filterAttribute1 = attributes[0];
  1275.                                 Attribute filterAttribute2 = attributes[1];
  1276.                                
  1277.                                 for (int i = infos.Count - 1; i >= 0; i--) {
  1278.                                     if (ShouldHideMember((MemberDescriptor)infos[i], filterAttribute1) || ShouldHideMember((MemberDescriptor)infos[i], filterAttribute2)) {
  1279.                                        
  1280.                                         infos.RemoveAt(i);
  1281.                                     }
  1282.                                 }
  1283.                                 break;
  1284.                             }
  1285.                             break;
  1286.                         default:
  1287.                             for (int i = infos.Count - 1; i >= 0; i--) {
  1288.                                 for (int j = 0; j < attributes.Length; j++) {
  1289.                                     if (ShouldHideMember((MemberDescriptor)infos[i], attributes[j])) {
  1290.                                         infos.RemoveAt(i);
  1291.                                         break;
  1292.                                     }
  1293.                                 }
  1294.                             }
  1295.                             break;
  1296.                     }
  1297.                 }
  1298.             }
  1299.            
  1300.             /// <devdoc>
  1301.             /// Retrieves the class level attributes for this type of componet that
  1302.             /// satisfy all of the passed-in attributes. For a class attribute to
  1303.             /// satisfy a particular attribute, the attribute must be present in the
  1304.             /// class's attribute list, or the attribute must match it's own default.
  1305.             /// </devdoc>
  1306.             public AttributeCollection GetAttributes(object component)
  1307.             {
  1308.                
  1309.                 // Another worst case collision scenario: we don't want the perf hit
  1310.                 // of taking a lock.
  1311.                 //
  1312.                 if (this.attributes == null) {
  1313.                     this.attributes = new AttributeCollection(new MemberList(this).GetAttributes());
  1314.                 }
  1315.                
  1316.                 AttributeCollection filteredAttributes = attributes;
  1317.                
  1318.                 if (component is IComponent) {
  1319.                     ITypeDescriptorFilterService tf = (ITypeDescriptorFilterService)GetService(component, typeof(ITypeDescriptorFilterService));
  1320.                     if (tf != null) {
  1321.                        
  1322.                         // The component's site is interested in filtering attributes. See if we
  1323.                         // have filtered them before. If so, then we're done. Otherwise we
  1324.                         // need to filter.
  1325.                         //
  1326.                         IDictionaryService ds = (IDictionaryService)GetService(component, typeof(IDictionaryService));
  1327.                         if (ds != null) {
  1328.                             AttributeCollection savedAttributes = null;
  1329.                            
  1330.                             lock (ds) {
  1331.                                 savedAttributes = (AttributeCollection)ds.GetValue(typeof(AttributeCollection));
  1332.                             }
  1333.                             if (savedAttributes != null) {
  1334.                                
  1335.                                 // Check that the filter that was used to create these attributes is the same
  1336.                                 // filter we currently have. People may replace the filter, and if we do
  1337.                                 // we must refresh the cache.
  1338.                                 //
  1339.                                 object savedFilter = ds.GetValue(typeof(ITypeDescriptorFilterService));
  1340.                                 if (savedFilter == null || savedFilter == tf) {
  1341.                                     filteredAttributes = savedAttributes;
  1342.                                 }
  1343.                             }
  1344.                         }
  1345.                        
  1346.                         if (filteredAttributes == attributes) {
  1347.                             Hashtable filterTable = new Hashtable(attributes.Count);
  1348.                            
  1349.                             if (attributes != null) {
  1350.                                 foreach (Attribute attr in attributes) {
  1351.                                     filterTable[attr.TypeId] = attr;
  1352.                                 }
  1353.                             }
  1354.                            
  1355.                             bool cache = tf.FilterAttributes((IComponent)component, filterTable);
  1356.                             Attribute[] temp = new Attribute[filterTable.Values.Count];
  1357.                             filterTable.Values.CopyTo(temp, 0);
  1358.                             filteredAttributes = new AttributeCollection(temp);
  1359.                            
  1360.                             if (ds != null && cache) {
  1361.                                 lock (ds) {
  1362.                                     ds.SetValue(typeof(AttributeCollection), filteredAttributes);
  1363.                                     ds.SetValue(typeof(ITypeDescriptorFilterService), tf);
  1364.                                 }
  1365.                             }
  1366.                         }
  1367.                     }
  1368.                 }
  1369.                
  1370.                 return filteredAttributes;
  1371.             }
  1372.            
  1373. /*
  1374.               The following code has been removed to fix FXCOP violations.  The code
  1375.               is left here incase it needs to be resurrected in the future.
  1376.             /// <devdoc>
  1377.             ///      Retrieves the designer for the given object, or null if there
  1378.             ///      is no designer.
  1379.             /// </devdoc>
  1380.             /// <internalonly/>
  1381.             private IDesigner GetComponentDesigner(object component) {
  1382.                 IDesigner designer = null;
  1383.                 if (component is IComponent) {
  1384.                     IComponent comp = (IComponent)component;
  1385.                     ISite site = comp.Site;
  1386.                     if (site != null) {
  1387.                         IDesignerHost host = (IDesignerHost)site.GetService(typeof(IDesignerHost));
  1388.                         if (host != null) {
  1389.                             designer = host.GetDesigner(comp);
  1390.                         }
  1391.                     }
  1392.                 }
  1393.                 return designer;
  1394.             }
  1395.             /// <devdoc>
  1396.             ///    Retrieves the type of this kind of component.
  1397.             /// </devdoc>
  1398.             public Type GetComponentType() {
  1399.                 return componentType;
  1400.             }
  1401.             */           
  1402.            
  1403.            
  1404.             /// <devdoc>
  1405.             /// Retrieves the type converter for this entry.
  1406.             /// Type converters are found by either looking for a
  1407.             /// TypeConverterAttribute on the component's class, or by
  1408.             /// traversing the base class heirarchy of the class until
  1409.             /// a primitive type is found.
  1410.             /// </devdoc>
  1411.             public TypeConverter GetConverter()
  1412.             {
  1413.                 if (converter == null) {
  1414.                     TypeConverterAttribute attr = (TypeConverterAttribute)GetAttributes(null)[typeof(TypeConverterAttribute)];
  1415.                     if (attr != null) {
  1416.                         Type converterType = GetTypeFromName(attr.ConverterTypeName);
  1417.                         if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) {
  1418.                             converter = (TypeConverter)CreateInstance(converterType);
  1419.                         }
  1420.                     }
  1421.                    
  1422.                     if (converter == null) {
  1423.                        
  1424.                         // We did not get a converter. Traverse up the base class chain until
  1425.                         // we find one in the stock hashtable.
  1426.                         //
  1427.                         converter = (TypeConverter)SearchIntrinsicTable(IntrinsicTypeConverters);
  1428.                         Debug.Assert(converter != null, "There is no intrinsic setup in the hashtable for the Object type");
  1429.                     }
  1430.                 }
  1431.                 return converter;
  1432.             }
  1433.            
  1434.             /// <devdoc>
  1435.             /// Retrieves the type converter for this entry.
  1436.             /// Type converters are found by either looking for a
  1437.             /// TypeConverterAttribute on the component's class, or by
  1438.             /// traversing the base class heirarchy of the class until
  1439.             /// a primitive type is found.
  1440.             /// </devdoc>
  1441.             public TypeConverter GetConverter(object component)
  1442.             {
  1443.                
  1444.                 TypeConverter obj = null;
  1445.                
  1446.                 // For components, the design time object for them may want to redefine the
  1447.                 // attributes. So, we search the attribute here based on the component. If found,
  1448.                 // we then search on the same attribute based on type. If the two don't match, then
  1449.                 // we cannot cache the value and must re-create every time. It is rare for a designer
  1450.                 // to override these attributes, so we want to be smart here.
  1451.                 //
  1452.                 TypeConverterAttribute attr = (TypeConverterAttribute)GetAttributes(component)[typeof(TypeConverterAttribute)];
  1453.                
  1454.                 if (attr != null) {
  1455.                     TypeConverterAttribute baseAttr = (TypeConverterAttribute)GetAttributes(null)[typeof(TypeConverterAttribute)];
  1456.                     if (baseAttr != attr) {
  1457.                         Type converterType = GetTypeFromName(attr.ConverterTypeName);
  1458.                         if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) {
  1459.                             obj = (TypeConverter)CreateInstance(converterType);
  1460.                         }
  1461.                     }
  1462.                 }
  1463.                
  1464.                 // No custom attribute, so we can just use the stock one.
  1465.                 //
  1466.                 if (obj == null) {
  1467.                     obj = GetConverter();
  1468.                 }
  1469.                
  1470.                 return obj;
  1471.             }
  1472.            
  1473.             /// <devdoc>
  1474.             /// Retrieves the default event.
  1475.             /// </devdoc>
  1476.             public EventDescriptor GetDefaultEvent(object component)
  1477.             {
  1478.                 string name = ((DefaultEventAttribute)GetAttributes(component)[typeof(DefaultEventAttribute)]).Name;
  1479.                 if (name != null) {
  1480.                     EventDescriptorCollection evts = GetEvents(component, null);
  1481.                     EventDescriptor evt = evts[name];
  1482.                     if (evt == null && evts.Count > 0) {
  1483.                         evt = evts[0];
  1484.                     }
  1485.                     return evt;
  1486.                 }
  1487.                 return null;
  1488.             }
  1489.            
  1490.             /// <devdoc>
  1491.             /// Retrieves the default property.
  1492.             /// </devdoc>
  1493.             public PropertyDescriptor GetDefaultProperty(object component)
  1494.             {
  1495.                 string name = ((DefaultPropertyAttribute)GetAttributes(component)[typeof(DefaultPropertyAttribute)]).Name;
  1496.                 if (name != null) {
  1497.                     return GetProperties(component, null)[name];
  1498.                 }
  1499.                 return null;
  1500.             }
  1501.            
  1502.             /// <devdoc>
  1503.             /// Retrieves an editor with the given base type. You may define multiple editor
  1504.             /// attributes for a type or property. This allows you to select the one you want.
  1505.             /// </devdoc>
  1506.             public object GetEditor(Type editorBaseType)
  1507.             {
  1508.                 object editor = null;
  1509.                
  1510.                 // Check the editors we've already created for this type.
  1511.                 //
  1512.                 lock (this) {
  1513.                     if (editorTypes != null) {
  1514.                         for (int i = 0; i < editorCount; i++) {
  1515.                             if (editorTypes[i] == editorBaseType) {
  1516.                                 return editors[i];
  1517.                             }
  1518.                         }
  1519.                     }
  1520.                 }
  1521.                
  1522.                 // If one wasn't found, then we must go through the attributes.
  1523.                 //
  1524.                 if (editor == null) {
  1525.                     AttributeCollection attrs = GetAttributes(null);
  1526.                    
  1527.                     for (int i = 0; i < attrs.Count; i++) {
  1528.                        
  1529.                         if (attrs[i] is EditorAttribute) {
  1530.                             EditorAttribute attr = (EditorAttribute)attrs[i];
  1531.                             Type attrEditorBaseType = GetTypeFromName(attr.EditorBaseTypeName);
  1532.                            
  1533.                             if (attrEditorBaseType != null && attrEditorBaseType == editorBaseType) {
  1534.                                 Type type = GetTypeFromName(attr.EditorTypeName);
  1535.                                
  1536.                                 if (type != null) {
  1537.                                     editor = CreateInstance(type);
  1538.                                     break;
  1539.                                 }
  1540.                             }
  1541.                         }
  1542.                     }
  1543.                    
  1544.                     // Check our set of intrinsic editors. These are provided by an external party.
  1545.                     //
  1546.                     if (editor == null) {
  1547.                         Hashtable intrinsicEditors = DebugTypeDescriptor.GetEditorTable(editorBaseType);
  1548.                         if (intrinsicEditors != null) {
  1549.                             editor = SearchIntrinsicTable(intrinsicEditors);
  1550.                         }
  1551.                     }
  1552.                    
  1553.                     // As a quick sanity check, check to see that the editor we got back is of
  1554.                     // the correct type.
  1555.                     //
  1556.                     if (editor != null && !editorBaseType.IsInstanceOfType(editor)) {
  1557.                         Debug.Fail("Editor " + editor.GetType().FullName + " is not an instance of " + editorBaseType.FullName + " but it is in that base types table.");
  1558.                         editor = null;
  1559.                     }
  1560.                    
  1561.                     // Now, another slot in our editor cache for next time
  1562.                     //
  1563.                     lock (this) {
  1564.                        
  1565.                         // we do a redundant check here for the editor, just in
  1566.                         // case another thread added it. We could have locked
  1567.                         // the entire method, but with all of the other
  1568.                         // callouts from this method deadlock becomes more probable.
  1569.                         //
  1570.                         // This is very safe, but I'm not sure there are any
  1571.                         // bad consequences of having duplicate editor types in the
  1572.                         // array. Better to be safe, but we do take an ever so minor
  1573.                         // hit here...
  1574.                         //
  1575.                         bool redundantEditor = false;
  1576.                        
  1577.                         if (editorTypes != null) {
  1578.                             for (int i = 0; i < editorCount; i++) {
  1579.                                 if (editorTypes[i] == editorBaseType) {
  1580.                                     redundantEditor = true;
  1581.                                     break;
  1582.                                 }
  1583.                             }
  1584.                         }
  1585.                        
  1586.                         if (!redundantEditor) {
  1587.                             if (editorTypes == null) {
  1588.                                 editorTypes = new Type[5];
  1589.                                 editors = new object[5];
  1590.                             }
  1591.                            
  1592.                             if (editorCount >= editorTypes.Length) {
  1593.                                 Type[] newTypes = new Type[editorTypes.Length * 2];
  1594.                                 object[] newEditors = new object[editors.Length * 2];
  1595.                                 Array.Copy(editorTypes, newTypes, editorTypes.Length);
  1596.                                 Array.Copy(editors, newEditors, editors.Length);
  1597.                                 editorTypes = newTypes;
  1598.                                 editors = newEditors;
  1599.                             }
  1600.                            
  1601.                             editorTypes[editorCount] = editorBaseType;
  1602.                             editors[editorCount++] = editor;
  1603.                         }
  1604.                     }
  1605.                 }
  1606.                
  1607.                 return editor;
  1608.             }
  1609.            
  1610.             /// <devdoc>
  1611.             /// Retrieves an editor with the given base type. You may define multiple editor
  1612.             /// attributes for a type or property. This allows you to select the one you want.
  1613.             /// </devdoc>
  1614.             public object GetEditor(object component, Type editorBaseType)
  1615.             {
  1616.                 object editor = null;
  1617.                
  1618.                 // For components, the design time object for them may want to redefine the
  1619.                 // attributes. So, we search the attribute here based on the component. If found,
  1620.                 // we then search on the same attribute based on type. If the two don't match, then
  1621.                 // we cannot cache the value and must re-create every time. It is rare for a designer
  1622.                 // to override these attributes, so we want to be smart here.
  1623.                 //
  1624.                 AttributeCollection attrs;
  1625.                
  1626.                 EditorAttribute attr = null;
  1627.                
  1628.                 attrs = GetAttributes(component);
  1629.                 for (int i = 0; i < attrs.Count; i++) {
  1630.                    
  1631.                     if (attrs[i] is EditorAttribute) {
  1632.                         EditorAttribute a = (EditorAttribute)attrs[i];
  1633.                         Type attrEditorBaseType = GetTypeFromName(a.EditorBaseTypeName);
  1634.                        
  1635.                         if (attrEditorBaseType != null && attrEditorBaseType == editorBaseType) {
  1636.                             attr = a;
  1637.                             break;
  1638.                         }
  1639.                     }
  1640.                 }
  1641.                
  1642.                 if (attr != null) {
  1643.                     // Now, compare this attribute against the one provided by the normal attribute set for the
  1644.                     // type. If it is the same, then we can resort to the normal GetEditor call. Otherwise,
  1645.                     // we must create the editor anew.
  1646.                     //
  1647.                     EditorAttribute baseAttr = null;
  1648.                    
  1649.                     attrs = GetAttributes(null);
  1650.                     for (int i = 0; i < attrs.Count; i++) {
  1651.                        
  1652.                         if (attrs[i] is EditorAttribute) {
  1653.                             EditorAttribute a = (EditorAttribute)attrs[i];
  1654.                             Type attrEditorBaseType = GetTypeFromName(a.EditorBaseTypeName);
  1655.                            
  1656.                             if (attrEditorBaseType != null && attrEditorBaseType == editorBaseType) {
  1657.                                 baseAttr = a;
  1658.                                 break;
  1659.                             }
  1660.                         }
  1661.                     }
  1662.                    
  1663.                     if (attr != baseAttr) {
  1664.                         // The attribute we should use is a custom attribute provided by the
  1665.                         // designer of this object. Create the editor directly. This will
  1666.                         // be fairly rare (nothing in .NET uses this today, and we're pretty
  1667.                         // broad), so I'm not too concerned with caching this.
  1668.                         //
  1669.                         Type type = GetTypeFromName(attr.EditorTypeName);
  1670.                         if (type != null) {
  1671.                             editor = CreateInstance(type);
  1672.                         }
  1673.                     }
  1674.                 }
  1675.                
  1676.                 if (editor == null) {
  1677.                     editor = GetEditor(editorBaseType);
  1678.                 }
  1679.                 else {
  1680.                     // As a quick sanity check, check to see that the editor we got back is of
  1681.                     // the correct type.
  1682.                     //
  1683.                     if (editor != null && !editorBaseType.IsInstanceOfType(editor)) {
  1684.                         Debug.Fail("Editor " + editor.GetType().FullName + " is not an instance of " + editorBaseType.FullName + " but it is in that base types table.");
  1685.                         editor = null;
  1686.                     }
  1687.                 }
  1688.                
  1689.                 return editor;
  1690.             }
  1691.            
  1692.             /// <devdoc>
  1693.             /// Retrieves events that satisfy all of the passed-in attributes.
  1694.             /// For an event to satisfy a particular attribute, the attribute must be
  1695.             /// present in the event's attribute list, or the attribute must match it's
  1696.             /// own default. The returned array is sorted based on the sort parameter.
  1697.             /// </devdoc>
  1698.             public EventDescriptorCollection GetEvents(object component, Attribute[] attributes)
  1699.             {
  1700.                 return GetEvents(component, attributes, false);
  1701.             }
  1702.            
  1703.             /// <devdoc>
  1704.             /// Retrieves events that satisfy all of the passed-in attributes.
  1705.             /// For an event to satisfy a particular attribute, the attribute must be
  1706.             /// present in the event's attribute list, or the attribute must match it's
  1707.             /// own default. The returned array is sorted based on the sort parameter.
  1708.             /// </devdoc>
  1709.             public EventDescriptorCollection GetEvents(object component, Attribute[] attributes, bool noFilter)
  1710.             {
  1711.                 // Worst case event collision scenario is two sets of events. Much cheaper than
  1712.                 // a constant lock.
  1713.                 //
  1714.                 if (this.events == null) {
  1715.                     this.events = new EventDescriptorCollection(new MemberList(this).GetEvents(), true);
  1716.                 }
  1717.                
  1718.                 EventDescriptorCollection filteredEvents = events;
  1719.                
  1720.                 if (component is IComponent) {
  1721.                     ITypeDescriptorFilterService tf = (ITypeDescriptorFilterService)GetService(component, typeof(ITypeDescriptorFilterService));
  1722.                    
  1723.                     if (!noFilter && tf != null) {
  1724.                         // The component's site is interested in filtering events. See if we
  1725.                         // have filtered them before. If so, then we're done. Otherwise we
  1726.                         // need to filter.
  1727.                         //
  1728.                         IDictionaryService ds = (IDictionaryService)GetService(component, typeof(IDictionaryService));
  1729.                         if (ds != null) {
  1730.                             EventDescriptorCollection savedEvents = null;
  1731.                            
  1732.                             lock (ds) {
  1733.                                 savedEvents = (EventDescriptorCollection)ds.GetValue(typeof(EventDescriptorCollection));
  1734.                             }
  1735.                            
  1736.                             if (savedEvents != null) {
  1737.                                
  1738.                                 // Check that the filter that was used to create these attributes is the same
  1739.                                 // filter we currently have. People may replace the filter, and if we do
  1740.                                 // we must refresh the cache.
  1741.                                 //
  1742.                                 object savedFilter = ds.GetValue(typeof(ITypeDescriptorFilterService));
  1743.                                 if (savedFilter == null || savedFilter == tf) {
  1744.                                     filteredEvents = savedEvents;
  1745.                                 }
  1746.                             }
  1747.                         }
  1748.                        
  1749.                         if (filteredEvents == events) {
  1750.                             Hashtable filterTable = new Hashtable(events.Count);
  1751.                            
  1752.                             if (events != null) {
  1753.                                 foreach (EventDescriptor ev in events) {
  1754.                                     filterTable[ev.Name] = ev;
  1755.                                 }
  1756.                             }
  1757.                            
  1758.                             bool cache = tf.FilterEvents((IComponent)component, filterTable);
  1759.                             EventDescriptor[] temp = new EventDescriptor[filterTable.Values.Count];
  1760.                             filterTable.Values.CopyTo(temp, 0);
  1761.                             filteredEvents = new EventDescriptorCollection(temp, true);
  1762.                            
  1763.                             if (ds != null && cache) {
  1764.                                 lock (ds) {
  1765.                                     ds.SetValue(typeof(EventDescriptorCollection), filteredEvents);
  1766.                                     ds.SetValue(typeof(ITypeDescriptorFilterService), tf);
  1767.                                 }
  1768.                             }
  1769.                         }
  1770.                     }
  1771.                 }
  1772.                
  1773.                 if (attributes != null && attributes.Length > 0) {
  1774.                     ArrayList list = new ArrayList(filteredEvents);
  1775.                     FilterMembers(typeof(EventDescriptor), list, attributes);
  1776.                     EventDescriptor[] temp = new EventDescriptor[list.Count];
  1777.                     list.CopyTo(temp, 0);
  1778.                     filteredEvents = new EventDescriptorCollection(temp, true);
  1779.                 }
  1780.                
  1781.                 return filteredEvents;
  1782.             }
  1783.            
  1784.             internal EventDescriptorCollection FilterEvents(object component, Attribute[] attributes, EventDescriptorCollection events)
  1785.             {
  1786.                 EventDescriptorCollection filteredEvents = events;
  1787.                
  1788.                 if (component is IComponent) {
  1789.                     ITypeDescriptorFilterService tf = (ITypeDescriptorFilterService)GetService(component, typeof(ITypeDescriptorFilterService));
  1790.                     if (tf != null) {
  1791.                         Hashtable filterTable = new Hashtable(events.Count);
  1792.                        
  1793.                         if (events != null) {
  1794.                             foreach (EventDescriptor ev in events) {
  1795.                                 filterTable[ev.Name] = ev;
  1796.                             }
  1797.                         }
  1798.                        
  1799.                         bool cache = tf.FilterEvents((IComponent)component, filterTable);
  1800.                         EventDescriptor[] temp = new EventDescriptor[filterTable.Values.Count];
  1801.                         filterTable.Values.CopyTo(temp, 0);
  1802.                         filteredEvents = new EventDescriptorCollection(temp, true);
  1803.                     }
  1804.                 }
  1805.                
  1806.                 if (attributes != null && attributes.Length > 0) {
  1807.                     ArrayList list = new ArrayList(filteredEvents);
  1808.                     FilterMembers(typeof(EventDescriptor), list, attributes);
  1809.                     EventDescriptor[] temp = new EventDescriptor[list.Count];
  1810.                     list.CopyTo(temp, 0);
  1811.                     filteredEvents = new EventDescriptorCollection(temp, true);
  1812.                 }
  1813.                
  1814.                 return filteredEvents;
  1815.             }
  1816.            
  1817.             /// <devdoc>
  1818.             /// Retrieves the filtered set of extended properties that this specific component receives. These
  1819.             /// extended properties wrap both the base extender info and the extender provider to make it appear as a
  1820.             /// regular property. The filtering is based on the given attributes.
  1821.             /// For an extended property to satisfy a particular attribute, the attribute must be
  1822.             /// present in the extended property's attribute list, or the attribute must match it's
  1823.             /// own default. The array is sorted based on the sort property.
  1824.             /// </devdoc>
  1825.             private ICollection GetExtendedProperties(IComponent comp, IExtenderProvider[] providers)
  1826.             {
  1827.                 Type componentType = comp.GetType();
  1828.                
  1829.                 Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "\tFound " + providers.Length.ToString(CultureInfo.InvariantCulture) + " providers");
  1830.                 IList list = new ArrayList();
  1831.                
  1832.                 for (int i = 0; i < providers.Length; i++) {
  1833.                    
  1834.                     if (!providers[i].CanExtend(comp)) {
  1835.                         continue;
  1836.                     }
  1837.                    
  1838.                     IExtenderProvider provider = providers[i];
  1839.                     Type providerType = provider.GetType();
  1840.                     ComponentEntry providerCompInfo = DebugTypeDescriptor.GetEntry(comp, providerType);
  1841.                    
  1842.                     IList providerWrappedExtenders = providerCompInfo.GetWrappedExtenders(provider);
  1843.                     Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "\twrapped extenders: " + providerWrappedExtenders.Count.ToString(CultureInfo.InvariantCulture));
  1844.                    
  1845.                     for (int j = 0; j < providerWrappedExtenders.Count; j++) {
  1846.                         PropertyDescriptor currentWrappedExtender = (PropertyDescriptor)providerWrappedExtenders[j];
  1847.                         Type receiverType = null;
  1848.                        
  1849.                         ExtenderProvidedPropertyAttribute eppa = (ExtenderProvidedPropertyAttribute)currentWrappedExtender.Attributes[typeof(ExtenderProvidedPropertyAttribute)];
  1850.                         if (eppa.ReceiverType != null) {
  1851.                             receiverType = eppa.ReceiverType;
  1852.                         }
  1853.                        
  1854.                         if (receiverType != null && receiverType.IsAssignableFrom(componentType)) {
  1855.                             list.Add(currentWrappedExtender);
  1856.                         }
  1857.                     }
  1858.                 }
  1859.                 return list;
  1860.             }
  1861.            
  1862.             /// <devdoc>
  1863.             /// This method is invoked during property filtering when a name
  1864.             /// collision is encountered between two properties. This returns
  1865.             /// a suffix that can be appended to the property name to make
  1866.             /// it unique. This will first attempt ot use the name of the
  1867.             /// extender. Failing that it will fall back to a static
  1868.             /// index that is continually incremented.
  1869.             /// </devdoc>
  1870.             private string GetExtenderCollisionSuffix(PropertyDescriptor prop)
  1871.             {
  1872.                 string suffix = null;
  1873.                
  1874.                 ExtenderProvidedPropertyAttribute exAttr = (ExtenderProvidedPropertyAttribute)prop.Attributes[typeof(ExtenderProvidedPropertyAttribute)];
  1875.                 if (exAttr != null) {
  1876.                     IExtenderProvider prov = exAttr.Provider;
  1877.                    
  1878.                     if (prov != null) {
  1879.                         string name = null;
  1880.                        
  1881.                         if (prov is IComponent) {
  1882.                             ISite site = ((IComponent)prov).Site;
  1883.                             if (site != null) {
  1884.                                 name = site.Name;
  1885.                             }
  1886.                         }
  1887.                        
  1888.                         if (name == null) {
  1889.                             name = (collisionIndex++).ToString(CultureInfo.InvariantCulture);
  1890.                         }
  1891.                        
  1892.                         suffix = "_" + name;
  1893.                     }
  1894.                 }
  1895.                
  1896.                 return suffix;
  1897.             }
  1898.            
  1899.             /// <devdoc>
  1900.             /// Retrieves the set of extender providers providing services for the given component.
  1901.             /// </devdoc>
  1902.             private IExtenderProvider[] GetExtenderProviders(ISite site)
  1903.             {
  1904.                 // See if this component's site has an IExtenderListService. If it
  1905.                 // does, we get our list of extenders from that, not from the container.
  1906.                 //
  1907.                 IExtenderListService listService = (IExtenderListService)site.GetService(typeof(IExtenderListService));
  1908.                
  1909.                 if (listService != null) {
  1910.                     return listService.GetExtenderProviders();
  1911.                 }
  1912.                 else {
  1913.                     ComponentCollection comps = site.Container.Components;
  1914.                     ArrayList exList = null;
  1915.                     foreach (IComponent comp in comps) {
  1916.                         if (comp is IExtenderProvider) {
  1917.                             if (exList == null) {
  1918.                                 exList = new ArrayList(2);
  1919.                             }
  1920.                             exList.Add(comp);
  1921.                         }
  1922.                     }
  1923.                     if (exList == null) {
  1924.                         return null;
  1925.                     }
  1926.                     else {
  1927.                         IExtenderProvider[] temp = new IExtenderProvider[exList.Count];
  1928.                         exList.CopyTo(temp, 0);
  1929.                         return temp;
  1930.                     }
  1931.                 }
  1932.             }
  1933.            
  1934.             /// <devdoc>
  1935.             /// Retrieves base extenders that this type of component provides that satisfy all of the
  1936.             /// passed-in attributes. For an extender to satisfy a particular attribute, the attribute
  1937.             /// must be present in the extender's attribute list, or the attribute must match it's
  1938.             /// own default. The array is sorted based on the sort parameter.
  1939.             /// </devdoc>
  1940.             public IList GetExtenders()
  1941.             {
  1942.                 if (this.extenders == null) {
  1943.                     this.extenders = new MemberList(this).GetExtenders();
  1944.                 }
  1945.                
  1946.                 return extenders;
  1947.             }
  1948.            
  1949.             /// <devdoc>
  1950.             /// Retrieves properties that satisfy all of the passed-in attributes.
  1951.             /// For a property to satisfy a particular attribute, the attribute must be
  1952.             /// present in the property's attribute list, or the attribute must match it's
  1953.             /// own default. The array is sorted based on the sort parameter.
  1954.             /// </devdoc>
  1955.             public PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes)
  1956.             {
  1957.                 return GetProperties(component, attributes, false);
  1958.             }
  1959.            
  1960.             /// <devdoc>
  1961.             /// Retrieves properties that satisfy all of the passed-in attributes.
  1962.             /// For a property to satisfy a particular attribute, the attribute must be
  1963.             /// present in the property's attribute list, or the attribute must match it's
  1964.             /// own default. The array is sorted based on the sort parameter.
  1965.             /// </devdoc>
  1966.             public PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes, bool noFilter)
  1967.             {
  1968.                 if (this.properties == null) {
  1969.                     this.properties = new PropertyDescriptorCollection(new MemberList(this).GetProperties(), true);
  1970.                 }
  1971.                
  1972.                 // We will use this to reconstruct the set of properties in case we have extenders, etc.
  1973.                 //
  1974.                 ArrayList allProps = null;
  1975.                 PropertyStash propStash = null;
  1976.                 bool inDictionary = false;
  1977.                
  1978.                 // This will be what we finally return. we default to the current static set of
  1979.                 // properties.
  1980.                 //
  1981.                 PropertyDescriptorCollection filteredProperties = properties;
  1982.                
  1983.                 if (component is IComponent) {
  1984.                     ISite site = ((IComponent)component).Site;
  1985.                     IExtenderProvider[] providers;
  1986.                    
  1987.                     if (site != null) {
  1988.                         providers = GetExtenderProviders(site);
  1989.                     }
  1990.                     else {
  1991.                         providers = null;
  1992.                     }
  1993.                    
  1994.                     ITypeDescriptorFilterService tf = null;
  1995.                     if (!noFilter)
  1996.                         tf = (ITypeDescriptorFilterService)GetService(component, typeof(ITypeDescriptorFilterService));
  1997.                    
  1998.                     // First, check to see if we found the properties in the dictionary service. If so, we
  1999.                     // can fall out immediately because we have already stashed them.
  2000.                     //
  2001.                     IDictionaryService ds = (IDictionaryService)GetService(component, typeof(IDictionaryService));
  2002.                     if (ds != null) {
  2003.                         object filterStash = null;
  2004.                        
  2005.                         lock (ds) {
  2006.                             propStash = (PropertyStash)ds.GetValue(typeof(PropertyStash));
  2007.                             filterStash = ds.GetValue(typeof(ITypeDescriptorFilterService));
  2008.                         }
  2009.                        
  2010.                         // Check that the filter that was used to create these attributes is the same
  2011.                         // filter we currently have. People may replace the filter, and if we do
  2012.                         // we must refresh the cache.
  2013.                         //
  2014.                         if ((filterStash == null || filterStash == tf) && propStash != null && propStash.ExtendersMatch(providers, component)) {
  2015.                             // Now check to see if the stashed array of attributes also matches. If
  2016.                             // it does, then we can return a stashed pre-filtered set of props.
  2017.                             //
  2018.                             if (propStash.AttributesMatch(attributes)) {
  2019.                                 filteredProperties = propStash.FilteredProperties;
  2020.                                 attributes = null;
  2021.                             }
  2022.                             else {
  2023.                                 allProps = propStash.Properties;
  2024.                             }
  2025.                             inDictionary = true;
  2026.                         }
  2027.                     }
  2028.                    
  2029.                     // Now check to see if the container wants to filter the set of properties.
  2030.                     //
  2031.                     if (!inDictionary) {
  2032.                         if (providers != null && providers.Length > 0) {
  2033.                             ICollection extendedProperties = GetExtendedProperties((IComponent)component, providers);
  2034.                            
  2035.                             if (extendedProperties != null && extendedProperties.Count > 0) {
  2036.                                 allProps = new ArrayList(properties.Count + extendedProperties.Count);
  2037.                                 allProps.AddRange(properties);
  2038.                                 allProps.AddRange(extendedProperties);
  2039.                             }
  2040.                         }
  2041.                        
  2042.                         if (tf != null) {
  2043.                             Hashtable filterTable = new Hashtable(properties.Count);
  2044.                            
  2045.                             if (allProps == null) {
  2046.                                 allProps = new ArrayList(properties);
  2047.                             }
  2048.                            
  2049.                             foreach (PropertyDescriptor p in allProps) {
  2050.                                 // We must handle the case of duplicate property names
  2051.                                 // because extender providers can provide any arbitrary
  2052.                                 // name. Our rule for this is simple: If we find a
  2053.                                 // duplicate name, resolve it back to the extender
  2054.                                 // provider that offered it and append "_" + the
  2055.                                 // provider name. If the provider has no name,
  2056.                                 // then append the object hash code.
  2057.                                 //
  2058.                                 if (filterTable.Contains(p.Name)) {
  2059.                                    
  2060.                                     // First, handle the new property. Because
  2061.                                     // of the order in which we added extended
  2062.                                     // properties above, we can be sure that
  2063.                                     // the new property is an extender. We
  2064.                                     // cannot be sure that the existing property
  2065.                                     // in the table is an extender, so we will
  2066.                                     // have to check.
  2067.                                     //
  2068.                                     string suffix = GetExtenderCollisionSuffix(p);
  2069.                                     Debug.Assert(suffix != null, "Name collision with non-extender property.");
  2070.                                     if (suffix != null) {
  2071.                                         filterTable[p.Name + suffix] = p;
  2072.                                     }
  2073.                                    
  2074.                                     // Now, handle the original property.
  2075.                                     //
  2076.                                     PropertyDescriptor origProp = (PropertyDescriptor)filterTable[p.Name];
  2077.                                     suffix = GetExtenderCollisionSuffix(origProp);
  2078.                                     if (suffix != null) {
  2079.                                         filterTable.Remove(p.Name);
  2080.                                         filterTable[origProp.Name + suffix] = origProp;
  2081.                                     }
  2082.                                 }
  2083.                                 else {
  2084.                                     filterTable[p.Name] = p;
  2085.                                 }
  2086.                             }
  2087.                            
  2088.                             bool cache = tf.FilterProperties((IComponent)component, filterTable);
  2089.                            
  2090.                             allProps = new ArrayList(filterTable.Values);
  2091.                            
  2092.                             if (ds != null && cache) {
  2093.                                 propStash = new PropertyStash(allProps, providers, component);
  2094.                                 lock (ds) {
  2095.                                     ds.SetValue(typeof(PropertyStash), propStash);
  2096.                                     ds.SetValue(typeof(ITypeDescriptorFilterService), tf);
  2097.                                 }
  2098.                                 inDictionary = true;
  2099.                             }
  2100.                         }
  2101.                     }
  2102.                 }
  2103.                
  2104.                 if (attributes != null && attributes.Length > 0) {
  2105.                     if (allProps == null) {
  2106.                         allProps = new ArrayList(properties);
  2107.                     }
  2108.                     else if (inDictionary) {
  2109.                         // If we just poked this into the dictionary, we must clone. Otherwise
  2110.                         // we will disrupt the dictionary.
  2111.                         //
  2112.                         allProps = new ArrayList(allProps);
  2113.                         inDictionary = false;
  2114.                     }
  2115.                     FilterMembers(typeof(PropertyDescriptor), allProps, attributes);
  2116.                 }
  2117.                
  2118.                 if (allProps != null) {
  2119.                    
  2120.                     PropertyDescriptor[] temp = new PropertyDescriptor[allProps.Count];
  2121.                     allProps.CopyTo(temp, 0);
  2122.                     filteredProperties = new PropertyDescriptorCollection(temp, true);
  2123.                     if (propStash != null) {
  2124.                         propStash.FilteredProperties = filteredProperties;
  2125.                         propStash.Attributes = attributes;
  2126.                     }
  2127.                 }
  2128.                
  2129.                 return filteredProperties;
  2130.             }
  2131.            
  2132.             internal PropertyDescriptorCollection FilterProperties(object component, Attribute[] attributes, PropertyDescriptorCollection properties)
  2133.             {
  2134.                 PropertyDescriptorCollection filteredProperties = properties;
  2135.                
  2136.                 ArrayList allProps = null;
  2137.                
  2138.                 if (component is IComponent) {
  2139.                     ITypeDescriptorFilterService tf = (ITypeDescriptorFilterService)GetService(component, typeof(ITypeDescriptorFilterService));
  2140.                    
  2141.                     if (tf != null) {
  2142.                         Hashtable filterTable = new Hashtable(properties.Count);
  2143.                        
  2144.                         foreach (PropertyDescriptor p in properties) {
  2145.                             string suffix = GetExtenderCollisionSuffix(p);
  2146.                             if (suffix == null)
  2147.                                 suffix = "";
  2148.                            
  2149.                             Debug.Assert(!filterTable.Contains(p.Name + suffix), "Overwriting PropertyDescriptor during filtering!!! " + p.Name + suffix);
  2150.                             filterTable[p.Name + suffix] = p;
  2151.                         }
  2152.                        
  2153.                         tf.FilterProperties((IComponent)component, filterTable);
  2154.                         allProps = new ArrayList(filterTable.Values);
  2155.                     }
  2156.                 }
  2157.                
  2158.                 if (attributes != null && attributes.Length > 0) {
  2159.                     if (allProps == null) {
  2160.                         allProps = new ArrayList(properties);
  2161.                     }
  2162.                     FilterMembers(typeof(PropertyDescriptor), allProps, attributes);
  2163.                 }
  2164.                
  2165.                 if (allProps != null) {
  2166.                     PropertyDescriptor[] temp = new PropertyDescriptor[allProps.Count];
  2167.                     allProps.CopyTo(temp, 0);
  2168.                     filteredProperties = new PropertyDescriptorCollection(temp, true);
  2169.                 }
  2170.                
  2171.                 return filteredProperties;
  2172.             }
  2173.            
  2174.             private object GetService(object component, Type type)
  2175.             {
  2176.                 if (component == null) {
  2177.                     throw new ArgumentNullException("component");
  2178.                 }
  2179.                
  2180.                 if (component is IComponent) {
  2181.                     ISite site = ((IComponent)component).Site;
  2182.                     if (site != null) {
  2183.                         return site.GetService(type);
  2184.                     }
  2185.                 }
  2186.                 return null;
  2187.             }
  2188.            
  2189.             /// <devdoc>
  2190.             /// Retrieves a type from a name. The Assembly of the type
  2191.             /// that this PropertyDescriptor came from is first checked,
  2192.             /// then a global Type.GetType is performed.
  2193.             /// </devdoc>
  2194.             protected Type GetTypeFromName(string typeName)
  2195.             {
  2196.                
  2197.                 if (typeName == null || typeName.Length == 0) {
  2198.                     return null;
  2199.                 }
  2200.                
  2201.                 int commaIndex = typeName.IndexOf(',');
  2202.                 Type t = null;
  2203.                
  2204.                 if (commaIndex == -1) {
  2205.                     t = componentType.Assembly.GetType(typeName);
  2206.                 }
  2207.                
  2208.                 if (t == null) {
  2209.                     t = Type.GetType(typeName);
  2210.                 }
  2211.                
  2212.                 return t;
  2213.             }
  2214.            
  2215.             /// <devdoc>
  2216.             /// Retrieves filtered, wrapped extended properties based on the provider and the extenderInfos for this type of provider.
  2217.             /// These are the extended properties that will be handed out to components through
  2218.             /// getExtendedProperties and getMergedProperties. These are wrapped versions of what is returned
  2219.             /// through getExtenders. They are filtered based on the attributes. They are sorted
  2220.             /// based on the sort property.
  2221.             /// </devdoc>
  2222.             private IList GetWrappedExtenders(IExtenderProvider provider)
  2223.             {
  2224.                 Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "GetWrappedExtenders");
  2225.                 if (wrappedExtenderTable == null) {
  2226.                     wrappedExtenderTable = new Hashtable();
  2227.                 }
  2228.                
  2229.                 if (provider == null) {
  2230.                     return null;
  2231.                 }
  2232.                
  2233.                 Type providerType = ((object)provider).GetType();
  2234.                 if (!componentType.IsAssignableFrom(providerType)) {
  2235.                     throw new ArgumentException(SR.GetString(SR.ErrorBadExtenderType, providerType.Name, componentType.Name), "provider");
  2236.                 }
  2237.                
  2238.                 bool sitedProvider = false;
  2239.                
  2240.                 if (provider is IComponent && ((IComponent)provider).Site != null) {
  2241.                     sitedProvider = true;
  2242.                 }
  2243.                
  2244.                 IList wrappedExtenders = null;
  2245.                
  2246.                 lock (this) {
  2247.                     wrappedExtenders = (IList)wrappedExtenderTable[provider];
  2248.                    
  2249.                     if (wrappedExtenders == null) {
  2250.                         Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "\tentry not found in table... creating");
  2251.                         IList extenders = GetExtenders();
  2252.                         Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "\tfound " + extenders.Count.ToString(CultureInfo.InvariantCulture) + " extenders");
  2253.                         wrappedExtenders = new ArrayList(extenders.Count);
  2254.                         for (int i = 0; i < extenders.Count; i++) {
  2255.                             DebugReflectPropertyDescriptor ex = (DebugReflectPropertyDescriptor)extenders[i];
  2256.                             Attribute[] attrs = null;
  2257.                            
  2258.                             // If the extender provider is not a sited component, then mark all
  2259.                             // of its properties as design time only, since there is no way we
  2260.                             // can persist them. We can assume this because this is only called if
  2261.                             // we could get the extender provider list from a component site.
  2262.                             //
  2263.                             if (!sitedProvider) {
  2264.                                 attrs = new Attribute[] {DesignOnlyAttribute.Yes};
  2265.                             }
  2266.                            
  2267.                             wrappedExtenders.Add(new DebugExtendedPropertyDescriptor(ex, ex.ExtenderGetReceiverType(), provider, attrs));
  2268.                         }
  2269.                         wrappedExtenderTable[provider] = wrappedExtenders;
  2270.                     }
  2271.                     else {
  2272.                         Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "\tentry found in table...");
  2273.                     }
  2274.                 }
  2275.                
  2276.                 return wrappedExtenders;
  2277.             }
  2278.            
  2279.             /// <devdoc>
  2280.             /// Searches the provided intrinsic hashtable for a match with the compnent type.
  2281.             /// At the beginning, the hashtable contains types for the various converters.
  2282.             /// As this table is searched, the types for these objects
  2283.             /// are replaced with instances, so we only create as needed. This method
  2284.             /// does the search up the base class hierarchy and will create instances
  2285.             /// for types as needed. These instances are stored back into the table
  2286.             /// for the base type, and for the original component type, for fast access.
  2287.             /// </devdoc>
  2288.             private object SearchIntrinsicTable(Hashtable table)
  2289.             {
  2290.                
  2291.                 object hashEntry = null;
  2292.                 Type baseType = componentType;
  2293.                
  2294.                 // We take a lock on this table. Nothing in this code calls out to
  2295.                 // other methods that lock, so it should be fairly safe to grab this
  2296.                 // lock. Also, this allows multiple intrinsic tables to be searched
  2297.                 // at once.
  2298.                 //
  2299.                 lock (table) {
  2300.                     // Here is where we put all special case logic for various intrinsics
  2301.                     // that cannot be directly mapped to a type.
  2302.                     //
  2303.                     if (componentType.IsCOMObject) {
  2304.                         // placeholder for COM converters, etc.
  2305.                     }
  2306.                     else {
  2307.                         if (componentType.IsEnum) {
  2308.                             hashEntry = table[intrinsicEnumKey];
  2309.                         }
  2310.                     }
  2311.                    
  2312.                     // Normal path -- start traversing up the class hierarchy
  2313.                     // looking for matches.
  2314.                     //
  2315.                     if (hashEntry == null) {
  2316.                         while (baseType != null && baseType != typeof(object)) {
  2317.                             hashEntry = table[baseType];
  2318.                            
  2319.                             // If the entry is a late-bound type, then try to
  2320.                             // resolve it.
  2321.                             //
  2322.                             if (hashEntry is string) {
  2323.                                 hashEntry = Type.GetType((string)hashEntry);
  2324.                                 if (hashEntry != null) {
  2325.                                     table[baseType] = hashEntry;
  2326.                                 }
  2327.                             }
  2328.                            
  2329.                             if (hashEntry != null) {
  2330.                                 break;
  2331.                             }
  2332.                            
  2333.                             baseType = baseType.BaseType;
  2334.                         }
  2335.                     }
  2336.                    
  2337.                     // Now make a scan through each value in the table, looking for interfaces.
  2338.                     // If we find one, see if the object implements the interface.
  2339.                     //
  2340.                     if (hashEntry == null) {
  2341.                        
  2342.                         foreach (object current in table.Keys) {
  2343.                             if (current is Type) {
  2344.                                 Type keyType = (Type)current;
  2345.                                 if (keyType.IsInterface && keyType.IsAssignableFrom(componentType)) {
  2346.                                     hashEntry = table[keyType];
  2347.                                    
  2348.                                     if (hashEntry is string) {
  2349.                                         hashEntry = Type.GetType((string)hashEntry);
  2350.                                         if (hashEntry != null) {
  2351.                                             table[componentType] = hashEntry;
  2352.                                         }
  2353.                                     }
  2354.                                    
  2355.                                     if (hashEntry != null) {
  2356.                                         break;
  2357.                                     }
  2358.                                 }
  2359.                             }
  2360.                         }
  2361.                     }
  2362.                    
  2363.                     // Finally, check to see if the component type is some unknown interface.
  2364.                     // We have a custom converter for that.
  2365.                     //
  2366.                     if (hashEntry == null && componentType.IsInterface) {
  2367.                         hashEntry = table[intrinsicReferenceKey];
  2368.                     }
  2369.                    
  2370.                     // Interfaces do not derive from object, so we
  2371.                     // must handle the case of no hash entry here.
  2372.                     //
  2373.                     if (hashEntry == null) {
  2374.                         hashEntry = table[typeof(object)];
  2375.                     }
  2376.                    
  2377.                     // If the entry is a type, create an instance of it and then
  2378.                     // replace the entry. This way we only need to create once.
  2379.                     // We can only do this if the object doesn't want a type
  2380.                     // in its constructor.
  2381.                     //
  2382.                     if (hashEntry is Type) {
  2383.                         Type type = (Type)hashEntry;
  2384.                         hashEntry = CreateInstance(type);
  2385.                        
  2386.                         if (type.GetConstructor(typeConstructor) == null) {
  2387.                             table[componentType] = hashEntry;
  2388.                         }
  2389.                     }
  2390.                 }
  2391.                
  2392.                 return hashEntry;
  2393.             }
  2394.            
  2395.             /// <devdoc>
  2396.             /// This function takes an info and an attribute and determines whether
  2397.             /// the info satisfies the particular attribute. This either means that the info
  2398.             /// contains the attribute or the info does not contain the attribute and the default
  2399.             /// for the attribute matches the passed in attribute.
  2400.             /// </devdoc>
  2401.             /// <internalonly/>
  2402.             static internal bool ShouldHideMember(MemberDescriptor info, Attribute attribute)
  2403.             {
  2404.                 if (info == null || attribute == null) {
  2405.                     return true;
  2406.                 }
  2407.                 Attribute infoAttribute = info.Attributes[attribute.GetType()];
  2408.                 if (infoAttribute == null)
  2409.                     return !attribute.IsDefaultAttribute();
  2410.                 else {
  2411.                     return !(attribute.Match(infoAttribute));
  2412.                 }
  2413.             }
  2414.            
  2415.             /// <devdoc>
  2416.             /// </devdoc>
  2417.             /// <internalonly/>
  2418.             private sealed class MemberList
  2419.             {
  2420.                 private Hashtable memberHash = new Hashtable();
  2421.                 private ComponentEntry owner;
  2422.                
  2423.                 public MemberList(ComponentEntry owner)
  2424.                 {
  2425.                     this.owner = owner;
  2426.                 }
  2427.                
  2428.                 public void AddMember(object member)
  2429.                 {
  2430.                     if (member is MemberDescriptor) {
  2431.                         memberHash[((MemberDescriptor)member).Name] = member;
  2432.                     }
  2433.                     else if (member is Attribute) {
  2434.                         object id = ((Attribute)member).TypeId;
  2435.                         memberHash[id] = member;
  2436.                     }
  2437.                     else {
  2438.                         memberHash[member.GetType()] = member;
  2439.                     }
  2440.                 }
  2441.                
  2442.                 internal Attribute[] GetAttributes()
  2443.                 {
  2444.                     Attribute[] ret = null;
  2445.                    
  2446.                     memberHash.Clear();
  2447.                    
  2448.                     Debug.WriteLineIf(CompDescrSwitch.TraceVerbose, "Getting attributes from " + owner.componentType.FullName);
  2449.                    
  2450.                     // Before we reflect on the type attributes, do the same for the type's interfaces, if it implements any.
  2451.                     // We add these in reflection order.
  2452.                     //
  2453.                     Type[] interfaces = owner.componentType.GetInterfaces();
  2454.                     foreach (Type iface in interfaces) {
  2455.                         // only do this for public interfaces
  2456.                         //
  2457.                         if ((iface.Attributes & (TypeAttributes.Public | TypeAttributes.NestedPublic)) != 0) {
  2458.                             ReflectGetCustomAttributes(iface, typeof(Attribute));
  2459.                         }
  2460.                     }
  2461.                    
  2462.                     // Now do the actual type. Last one in wins.
  2463.                     //
  2464.                     ReflectGetCustomAttributes(owner.componentType, typeof(Attribute));
  2465.                    
  2466.                     // NOTE : You cannot combine designer attributes with the base class attributes.
  2467.                     // To find the designer you must get the attributes on this class, thus causing
  2468.                     // an infinite recursion... don't do that!
  2469.                     //
  2470.                     ret = new Attribute[memberHash.Values.Count];
  2471.                     memberHash.Values.CopyTo(ret, 0);
  2472.                    
  2473.                     return ret;
  2474.                 }
  2475.                
  2476.                 /// <devdoc>
  2477.                 /// </devdoc>
  2478.                 /// <internalonly/>
  2479.                 internal EventDescriptor[] GetEvents()
  2480.                 {
  2481.                     EventDescriptor[] ret = null;
  2482.                    
  2483.                     memberHash.Clear();
  2484.                    
  2485.                     ReflectGetEvents(owner.componentType);
  2486.                    
  2487.                     ret = new EventDescriptor[memberHash.Values.Count];
  2488.                     memberHash.Values.CopyTo(ret, 0);
  2489.                    
  2490.                     return ret;
  2491.                 }
  2492.                
  2493.                 /// <devdoc>
  2494.                 /// </devdoc>
  2495.                 /// <internalonly/>
  2496.                 internal IList GetExtenders()
  2497.                 {
  2498.                     ArrayList ret = null;
  2499.                    
  2500.                     memberHash.Clear();
  2501.                    
  2502.                     ReflectGetExtenders(owner.componentType);
  2503.                    
  2504.                     ret = new ArrayList(memberHash.Values);
  2505.                    
  2506.                     return ret;
  2507.                 }
  2508.                
  2509.                 internal PropertyDescriptor[] GetProperties()
  2510.                 {
  2511.                     PropertyDescriptor[] ret = null;
  2512.                    
  2513.                     memberHash.Clear();
  2514.                    
  2515.                     ReflectGetProperties(owner.componentType);
  2516.                    
  2517.                     ret = new PropertyDescriptor[memberHash.Values.Count];
  2518.                     memberHash.Values.CopyTo(ret, 0);
  2519.                    
  2520.                     return ret;
  2521.                 }
  2522.                
  2523.                 /// <devdoc>
  2524.                 /// Reflects on a class and it's base classes to find any custom
  2525.                 /// attributes of the specified type. The comparison to the metadataType
  2526.                 /// is a not strict comparison and will return derived instances.
  2527.                 /// </devdoc>
  2528.                 private void ReflectGetCustomAttributes(Type classToReflect, Type metadataType)
  2529.                 {
  2530.                     AttributeCollection baseAttributes = null;
  2531.                     Hashtable attrHash = new Hashtable();
  2532.                     #if DEBUG
  2533.                     if (CompDescrSwitch.TraceVerbose) {
  2534.                         Debug.WriteLine(" retrieving metadata for " + classToReflect.FullName);
  2535.                         Debug.WriteLine(" classToRefelct: " + classToReflect.FullName);
  2536.                         Debug.WriteLine(" metadataType: " + metadataType.FullName);
  2537.                     }
  2538.                     #endif
  2539.                    
  2540.                     // We only want to reflect on one level at a time,
  2541.                     // so if we have a base class above object, we get the
  2542.                     // attributes for that first.
  2543.                     //
  2544.                     Type baseType = classToReflect.BaseType;
  2545.                     if (baseType != typeof(object) && baseType != null) {
  2546.                         baseAttributes = DebugTypeDescriptor.GetAttributes(baseType);
  2547.                     }
  2548.                    
  2549.                     if (baseAttributes != null && baseAttributes.Count > 0) {
  2550.                         foreach (Attribute attr in baseAttributes) {
  2551.                             Type attrType = attr.GetType();
  2552.                             if (metadataType.IsAssignableFrom(attrType)) {
  2553.                                 attrHash[attr.TypeId] = attr;
  2554.                             }
  2555.                         }
  2556.                     }
  2557.                    
  2558.                     // now get our attributes
  2559.                     //
  2560.                     object[] attributes = DebugTypeDescriptor.GetCustomAttributes(classToReflect);
  2561.                    
  2562.                     foreach (Attribute attr in attributes) {
  2563.                         Type attrType = attr.GetType();
  2564.                         if (metadataType.IsAssignableFrom(attrType)) {
  2565.                             attrHash[attr.TypeId] = attr;
  2566.                         }
  2567.                     }
  2568.                    
  2569.                     // push the values up to the top level
  2570.                     //
  2571.                     foreach (Attribute attr in attrHash.Values) {
  2572.                         AddMember(attr);
  2573.                     }
  2574.                 }
  2575.                
  2576.                 /// <devdoc>
  2577.                 /// Reflects on a class to find the events for that class. This
  2578.                 /// calls AddMember for each new event that it finds.
  2579.                 /// </devdoc>
  2580.                 private void ReflectGetEvents(Type classToReflect)
  2581.                 {
  2582.                     Type currentType = classToReflect;
  2583.                     Hashtable eventHash = null;
  2584.                    
  2585.                     EventDescriptorCollection baseTypeEvents = null;
  2586.                    
  2587.                    
  2588.                     // We only want to reflect on one level at a time,
  2589.                     // so if we have a base class above object, we get the
  2590.                     // properties for that first.
  2591.                     //
  2592.                     Type baseType = classToReflect.BaseType;
  2593.                     if (baseType != typeof(object) && baseType != null) {
  2594.                         baseTypeEvents = DebugTypeDescriptor.GetEvents(baseType);
  2595.                     }
  2596.                    
  2597.                     // for this particular type, we get _only_ the properties
  2598.                     // declared on that type
  2599.                     //
  2600.                     EventInfo[] events = classToReflect.GetEvents(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
  2601.                    
  2602.                     // if we have properties from the base type, stick them into
  2603.                     // a hashtable because we'll want to override them with re-declared
  2604.                     // properties on this particular type.
  2605.                     //
  2606.                     if (baseTypeEvents != null && baseTypeEvents.Count > 0) {
  2607.                         eventHash = new Hashtable();
  2608.                         foreach (EventDescriptor ed in baseTypeEvents) {
  2609.                             eventHash[ed.Name] = ed;
  2610.                         }
  2611.                     }
  2612.                    
  2613.                     // now walk each event we got an make sure it's got an add and a remove
  2614.                     //
  2615.                     foreach (EventInfo eventInfo in events) {
  2616.                         if ((!(eventInfo.DeclaringType.IsPublic || eventInfo.DeclaringType.IsNestedPublic)) && (eventInfo.DeclaringType.Assembly == typeof(DebugTypeDescriptor).Assembly)) {
  2617.                             continue;
  2618.                         }
  2619.                        
  2620.                         MethodInfo addMethod = eventInfo.GetAddMethod();
  2621.                         MethodInfo removeMethod = eventInfo.GetRemoveMethod();
  2622.                         bool allGood = addMethod != null && removeMethod != null;
  2623.                        
  2624.                         // if we have a base list, push the new descriptor
  2625.                         // into the hashtable, otherwise just add it directly.
  2626.                         //
  2627.                         if (eventHash != null) {
  2628.                             EventInfo currentEvent = eventInfo;
  2629.                            
  2630.                             // okay, we have to get tricky here...
  2631.                             // if we got an event without an add and remove...which means one is defined on a base class
  2632.                             //
  2633.                             if (!allGood) {
  2634.                                 if (eventHash.Contains(eventInfo.Name)) {
  2635.                                    
  2636.                                     // a base class has a property for this,
  2637.                                     // so we should just pick up it's
  2638.                                     // getter.
  2639.                                     //
  2640.                                     EventDescriptor basePd = (EventDescriptor)eventHash[eventInfo.Name];
  2641.                                     Type declaringType = basePd.ComponentType;
  2642.                                     if (declaringType != null) {
  2643.                                         EventInfo baseEvent = declaringType.GetEvent(eventInfo.Name);
  2644.                                         if (baseEvent != null && baseEvent.GetAddMethod() != null && baseEvent.GetRemoveMethod() != null) {
  2645.                                             currentEvent = baseEvent;
  2646.                                         }
  2647.                                     }
  2648.                                 }
  2649.                             }
  2650.                            
  2651.                             // push the new info into the hash table.
  2652.                             //
  2653.                             eventHash[eventInfo.Name] = new DebugReflectEventDescriptor(classToReflect, currentEvent);
  2654.                         }
  2655.                         else {
  2656.                             AddMember(new DebugReflectEventDescriptor(classToReflect, eventInfo));
  2657.                         }
  2658.                        
  2659.                     }
  2660.                    
  2661.                     // now all the things in the hashtable are our "actual" list
  2662.                     // of events, so just set it directly.
  2663.                     //
  2664.                     if (eventHash != null) {
  2665.                         this.memberHash = eventHash;
  2666.                     }
  2667.                 }
  2668.                
  2669.                 /// <devdoc>
  2670.                 /// Reflects on a class to find the extender properties for that class. This
  2671.                 /// calls AddMember for each new property that it finds.
  2672.                 /// </devdoc>
  2673.                 private void ReflectGetExtenders(Type classToReflect)
  2674.                 {
  2675.                     foreach (Attribute attr in DebugTypeDescriptor.GetAttributes(classToReflect)) {
  2676.                         if (attr is ProvidePropertyAttribute) {
  2677.                             ProvidePropertyAttribute provided = (ProvidePropertyAttribute)attr;
  2678.                            
  2679.                             Type receiverType = Type.GetType(provided.ReceiverTypeName);
  2680.                            
  2681.                             if (receiverType != null) {
  2682.                                 MethodInfo getMethod = classToReflect.GetMethod("Get" + provided.PropertyName, new Type[] {receiverType});
  2683.                                 if (getMethod != null && !getMethod.IsStatic && getMethod.IsPublic) {
  2684.                                     MethodInfo setMethod = classToReflect.GetMethod("Set" + provided.PropertyName, new Type[] {receiverType, getMethod.ReturnType});
  2685.                                    
  2686.                                     if (setMethod != null && (setMethod.IsStatic || !setMethod.IsPublic)) {
  2687.                                         setMethod = null;
  2688.                                     }
  2689.                                     AddMember(new DebugReflectPropertyDescriptor(classToReflect, provided.PropertyName, getMethod.ReturnType, receiverType, getMethod, setMethod, null));
  2690.                                 }
  2691.                             }
  2692.                         }
  2693.                     }
  2694.                 }
  2695.                
  2696.                 /// <devdoc>
  2697.                 /// Reflects on a class to find the properties for that class. This
  2698.                 /// calls AddMember for each new property that it finds.
  2699.                 /// </devdoc>
  2700.                 private void ReflectGetProperties(Type classToReflect)
  2701.                 {
  2702.                     Type currentType = classToReflect;
  2703.                     Hashtable propertyHash = null;
  2704.                    
  2705.                     PropertyDescriptorCollection baseTypeProps = null;
  2706.                    
  2707.                     // We only want to reflect on one level at a time,
  2708.                     // so if we have a base class above object, we get the
  2709.                     // properties for that first.
  2710.                     //
  2711.                     Type baseType = classToReflect.BaseType;
  2712.                     if (baseType != typeof(object) && baseType != null) {
  2713.                         baseTypeProps = DebugTypeDescriptor.GetProperties(baseType);
  2714.                     }
  2715.                    
  2716.                     // for this particular type, we get _only_ the properties
  2717.                     // declared on that type
  2718.                     //
  2719.                     PropertyInfo[] props = classToReflect.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
  2720.                    
  2721.                     // if we have properties from the base type, stick them into
  2722.                     // a hashtable because we'll want to override them with re-declared
  2723.                     // properties on this particular type.
  2724.                     //
  2725.                     if (baseTypeProps != null && baseTypeProps.Count > 0) {
  2726.                         propertyHash = new Hashtable();
  2727.                         foreach (PropertyDescriptor pd in baseTypeProps) {
  2728.                             propertyHash[pd.Name] = pd;
  2729.                         }
  2730.                     }
  2731.                    
  2732.                     // now walk each property we got an make sure it's got a getter and a setter
  2733.                     //
  2734.                     foreach (PropertyInfo pi in props) {
  2735.                         if ((!(pi.DeclaringType.IsPublic || pi.DeclaringType.IsNestedPublic)) && (pi.DeclaringType.Assembly == typeof(DebugTypeDescriptor).Assembly)) {
  2736.                             continue;
  2737.                         }
  2738.                        
  2739.                         bool addProp = true;
  2740.                         MethodInfo getMethod = pi.GetGetMethod();
  2741.                         MethodInfo setMethod = pi.GetSetMethod();
  2742.                         MethodInfo mi = getMethod;
  2743.                        
  2744.                         // first just look to see if we have a getter
  2745.                         //
  2746.                         if (mi != null) {
  2747.                             // Ensure the get method has no parameters.
  2748.                             //
  2749.                             ParameterInfo[] parameters = mi.GetParameters();
  2750.                            
  2751.                             if (parameters != null && parameters.Length != 0) {
  2752.                                 addProp = false;
  2753.                             }
  2754.                         }
  2755.                         else {
  2756.                             addProp = false;
  2757.                         }
  2758.                        
  2759.                         // build the property descriptor
  2760.                         // for this property.
  2761.                         //
  2762.                         if (addProp && mi != null && !mi.IsStatic && mi.IsPublic) {
  2763.                            
  2764.                             // if we have a base list, push the new descriptor
  2765.                             // into the hashtable, otherwise just add it directly.
  2766.                             //
  2767.                             if (propertyHash != null) {
  2768.                                
  2769.                                 // okay, we have to get tricky here...
  2770.                                 // if we got a property without a GetMethod, see if there's one in here we can use
  2771.                                 //
  2772.                                 if (getMethod == null) {
  2773.                                     if (propertyHash.Contains(pi.Name)) {
  2774.                                        
  2775.                                         // a base class has a property for this,
  2776.                                         // so we should just pick up it's
  2777.                                         // getter.
  2778.                                         //
  2779.                                         PropertyDescriptor basePd = (PropertyDescriptor)propertyHash[pi.Name];
  2780.                                         Type declaringType = basePd.ComponentType;
  2781.                                         if (declaringType != null) {
  2782.                                             PropertyInfo baseProp = declaringType.GetProperty(pi.Name, pi.PropertyType);
  2783.                                             if (baseProp != null) {
  2784.                                                 getMethod = baseProp.GetGetMethod();
  2785.                                             }
  2786.                                             else {
  2787.                                                 Debug.Fail("Base prop list has '" + pi.Name + "' but reflection didn't find it.");
  2788.                                             }
  2789.                                         }
  2790.                                     }
  2791.                                 }
  2792.                                
  2793.                                 // push the new info into the hash table.
  2794.                                 //
  2795.                                 propertyHash[pi.Name] = new DebugReflectPropertyDescriptor(classToReflect, pi.Name, pi.PropertyType, pi, getMethod, setMethod, null);
  2796.                                 ;
  2797.                             }
  2798.                             else {
  2799.                                 AddMember(new DebugReflectPropertyDescriptor(classToReflect, pi.Name, pi.PropertyType, pi, getMethod, setMethod, null));
  2800.                             }
  2801.                         }
  2802.                     }
  2803.                    
  2804.                     // now all the things in the hashtable are our "actual" list
  2805.                     // of properties, so just set it directly.
  2806.                     //
  2807.                     if (propertyHash != null) {
  2808.                         this.memberHash = propertyHash;
  2809.                     }
  2810.                    
  2811.                 }
  2812.             }
  2813.            
  2814.            
  2815. /*
  2816.               The following code has been removed to fix FXCOP violations.  The code
  2817.               is left here incase it needs to be resurrected in the future.
  2818.             // This is a private class used to contain events while we hash
  2819.             //
  2820.             private class EventHashHolder {
  2821.                 public EventInfo RealEvent;
  2822.                 public string Name;
  2823.                 public Type ReflectedType;
  2824.                 public MethodInfo AddMethod;
  2825.                 public MethodInfo RemoveMethod;
  2826.                
  2827.                 public EventHashHolder(EventInfo evt) {
  2828.                     RealEvent = evt;
  2829.                     Name = evt.Name;
  2830.                     AddMethod = evt.GetAddMethod();
  2831.                     RemoveMethod = evt.GetRemoveMethod();
  2832.                     if (AddMethod != null && RemoveMethod != null) {
  2833.                         ReflectedType = evt.EventHandlerType;
  2834.                     }
  2835.                 }
  2836.                
  2837.                 public EventHashHolder(string name, Type reflectedType, MethodInfo addMethod, MethodInfo removeMethod) {
  2838.                     Name = name;
  2839.                     ReflectedType = reflectedType;
  2840.                     AddMethod = addMethod;
  2841.                     RemoveMethod = removeMethod;
  2842.                 }
  2843.             }
  2844.            
  2845.             // This is a private class used to contain properties while we hash
  2846.             //
  2847.             private class PropertyHashHolder {
  2848.                 public string Name;
  2849.                 public Type PropertyType;
  2850.                 public MethodInfo GetMethod;
  2851.                 public MethodInfo SetMethod;
  2852.                 public PropertyInfo PropertyInfo;
  2853.                
  2854.                 public PropertyHashHolder(PropertyInfo prop) {
  2855.                     Name = prop.Name;
  2856.                     PropertyType = prop.PropertyType;
  2857.                     GetMethod = prop.GetGetMethod();
  2858.                     SetMethod = prop.GetSetMethod();
  2859.                     PropertyInfo = prop;
  2860.                 }
  2861.             }
  2862.             */           
  2863.            
  2864.             // This is a private class used to stash a set of properties on
  2865.             // a component's site so we can quickly recover them.
  2866.             //
  2867.             private class PropertyStash
  2868.             {
  2869.                 private long extenderHash;
  2870.                 public ArrayList Properties;
  2871.                 public PropertyDescriptorCollection FilteredProperties;
  2872.                 public Attribute[] Attributes;
  2873.                
  2874.                 public PropertyStash(ArrayList props, IExtenderProvider[] providers, object instance)
  2875.                 {
  2876.                     Properties = props;
  2877.                     extenderHash = HashExtenders(providers, instance);
  2878.                 }
  2879.                
  2880.                 // This will return true if the current set of attributes match
  2881.                 // the given set.
  2882.                 //
  2883.                 public bool AttributesMatch(Attribute[] attributes)
  2884.                 {
  2885.                     int ourCount = (Attributes == null ? 0 : Attributes.Length);
  2886.                     int count = (attributes == null ? 0 : attributes.Length);
  2887.                    
  2888.                     if (ourCount != count) {
  2889.                         return false;
  2890.                     }
  2891.                    
  2892.                     bool match = true;
  2893.                    
  2894.                     for (int i = 0; i < ourCount; i++) {
  2895.                         for (int j = 0; j < count; j++) {
  2896.                             if (!Attributes[i].Match(attributes[j])) {
  2897.                                 match = false;
  2898.                                 break;
  2899.                             }
  2900.                         }
  2901.                     }
  2902.                    
  2903.                     return match;
  2904.                 }
  2905.                
  2906.                 // This will return true if the given array if extenders is the same
  2907.                 // as the set that these stashed properties were created with.
  2908.                 //
  2909.                 public bool ExtendersMatch(IExtenderProvider[] providers, object instance)
  2910.                 {
  2911.                     long hash = HashExtenders(providers, instance);
  2912.                     return extenderHash == hash;
  2913.                 }
  2914.                
  2915.                 // This is a simple hashing algorithm that attempts to create
  2916.                 // a unique number for a given set of extender providers.
  2917.                 //
  2918.                 private long HashExtenders(IExtenderProvider[] providers, object instance)
  2919.                 {
  2920.                     long hash = 0;
  2921.                    
  2922.                     int count = (providers == null ? 0 : providers.Length);
  2923.                     for (int i = 0; i < count; i++) {
  2924.                         if (providers[i].CanExtend(instance)) {
  2925.                             hash += providers[i].GetHashCode();
  2926.                         }
  2927.                     }
  2928.                     return hash;
  2929.                 }
  2930.             }
  2931.         }
  2932.        
  2933.         class MemberDescriptorComparer : IComparer
  2934.         {
  2935.             public static readonly MemberDescriptorComparer Instance = new MemberDescriptorComparer();
  2936.            
  2937.             [SuppressMessage("Microsoft.Globalization", "CA130:UseOrdinalStringComparison", MessageId = "System.String.Compare(System.String,System.String,System.Boolean,System.Globalization.CultureInfo)")]
  2938.             public int Compare(object left, object right)
  2939.             {
  2940.                 return string.Compare(((MemberDescriptor)left).Name, ((MemberDescriptor)right).Name, false, CultureInfo.InvariantCulture);
  2941.             }
  2942.         }
  2943.     }
  2944. }
  2945. #endif

Developer Fusion