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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="ReflectTypeDescriptionProvider.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. namespace System.ComponentModel
  16. {
  17.    
  18.     using System;
  19.     using System.Collections;
  20.     using System.Collections.Specialized;
  21.     using System.ComponentModel.Design;
  22.     using System.Diagnostics;
  23.     using System.Globalization;
  24.     using System.Reflection;
  25.     using System.Security;
  26.     using System.Security.Permissions;
  27.    
  28.     /// <devdoc>
  29.     /// This type description provider provides type information through
  30.     /// reflection. Unless someone has provided a custom type description
  31.     /// provider for a type or instance, or unless an instance implements
  32.     /// ICustomTypeDescriptor, any query for type information will go through
  33.     /// this class. There should be a single instance of this class associated
  34.     /// with "object", as it can provide all type information for any type.
  35.     /// </devdoc>
  36.     [HostProtection(SharedState = true)]
  37.     internal sealed class ReflectTypeDescriptionProvider : TypeDescriptionProvider
  38.     {
  39.         // Hastable of Type -> ReflectedTypeData. ReflectedTypeData contains all
  40.         // of the type information we have gathered for a given type.
  41.         //
  42.         private Hashtable _typeData;
  43.        
  44.         // This is the signature we look for when creating types that are generic, but
  45.         // want to know what type they are dealing with. Enums are a good example of this;
  46.         // there is one enum converter that can work with all enums, but it needs to know
  47.         // the type of enum it is dealing with.
  48.         //
  49.         private static Type[] _typeConstructor = new Type[] {typeof(Type)};
  50.        
  51.         // This is where we store the various converters, etc for the intrinsic types.
  52.         //
  53.         private static Hashtable _editorTables;
  54.         private static Hashtable _intrinsicTypeConverters;
  55.        
  56.         // For converters, etc that are bound to class attribute data, rather than a class
  57.         // type, we have special key sentinel values that we put into the hash table.
  58.         //
  59.         private static object _intrinsicReferenceKey = new object();
  60.         private static object _intrinsicNullableKey = new object();
  61.        
  62.         // The key we put into IDictionaryService to store our cache dictionary.
  63.         //
  64.         private static object _dictionaryKey = new object();
  65.        
  66.         // This is a cache on top of core reflection. The cache
  67.         // builds itself recursively, so if you ask for the properties
  68.         // on Control, Component and object are also automatically filled
  69.         // in. The keys to the property and event caches are types.
  70.         // The keys to the attribute cache are either MemberInfos or types.
  71.         //
  72.         private static Hashtable _propertyCache;
  73.         private static Hashtable _eventCache;
  74.         private static Hashtable _attributeCache;
  75.         private static Hashtable _extendedPropertyCache;
  76.        
  77.         // These are keys we stuff into our object cache. We use this
  78.         // cache data to store extender provider info for an object.
  79.         //
  80.         private static readonly Guid _extenderProviderKey = Guid.NewGuid();
  81.         private static readonly Guid _extenderPropertiesKey = Guid.NewGuid();
  82.         private static readonly Guid _extenderProviderPropertiesKey = Guid.NewGuid();
  83.        
  84.         // These are attribute that, when we discover them on interfaces, we do
  85.         // not merge them into the attribute set for a class.
  86.         private static readonly Type[] _skipInterfaceAttributeList = new Type[] {typeof(System.Runtime.InteropServices.GuidAttribute), typeof(System.Runtime.InteropServices.ComVisibleAttribute), typeof(System.Runtime.InteropServices.InterfaceTypeAttribute)};
  87.        
  88.        
  89.         static internal Guid ExtenderProviderKey {
  90.             get { return _extenderProviderKey; }
  91.         }
  92.        
  93.        
  94.         private static object _internalSyncObject = new object();
  95.         /// <devdoc>
  96.         /// Creates a new ReflectTypeDescriptionProvider. The type is the
  97.         /// type we will obtain type information for.
  98.         /// </devdoc>
  99.         internal ReflectTypeDescriptionProvider()
  100.         {
  101.             TypeDescriptor.Trace("Reflect : Creating ReflectTypeDescriptionProvider");
  102.         }
  103.        
  104.         /// <devdoc>
  105.         /// This is a table we create for intrinsic types.
  106.         /// There should be entries here ONLY for intrinsic
  107.         /// types, as all other types we should be able to
  108.         /// add attributes directly as metadata.
  109.         /// </devdoc>
  110.         private static Hashtable IntrinsicTypeConverters {
  111.             get {
  112.                 // It is not worth taking a lock for this -- worst case of a collision
  113.                 // would build two tables, one that garbage collects very quickly.
  114.                 //
  115.                 if (_intrinsicTypeConverters == null) {
  116.                     Hashtable temp = new Hashtable();
  117.                    
  118.                     // Add the intrinsics
  119.                     //
  120.                     temp[typeof(bool)] = typeof(BooleanConverter);
  121.                     temp[typeof(byte)] = typeof(ByteConverter);
  122.                     temp[typeof(sbyte)] = typeof(SByteConverter);
  123.                     temp[typeof(char)] = typeof(CharConverter);
  124.                     temp[typeof(double)] = typeof(DoubleConverter);
  125.                     temp[typeof(string)] = typeof(StringConverter);
  126.                     temp[typeof(int)] = typeof(Int32Converter);
  127.                     temp[typeof(short)] = typeof(Int16Converter);
  128.                     temp[typeof(long)] = typeof(Int64Converter);
  129.                     temp[typeof(float)] = typeof(SingleConverter);
  130.                     temp[typeof(UInt16)] = typeof(UInt16Converter);
  131.                     temp[typeof(UInt32)] = typeof(UInt32Converter);
  132.                     temp[typeof(UInt64)] = typeof(UInt64Converter);
  133.                     temp[typeof(object)] = typeof(TypeConverter);
  134.                     temp[typeof(void)] = typeof(TypeConverter);
  135.                     temp[typeof(CultureInfo)] = typeof(CultureInfoConverter);
  136.                     temp[typeof(DateTime)] = typeof(DateTimeConverter);
  137.                     temp[typeof(decimal)] = typeof(DecimalConverter);
  138.                     temp[typeof(TimeSpan)] = typeof(TimeSpanConverter);
  139.                     temp[typeof(Guid)] = typeof(GuidConverter);
  140.                     temp[typeof(Array)] = typeof(ArrayConverter);
  141.                     temp[typeof(ICollection)] = typeof(CollectionConverter);
  142.                     temp[typeof(Enum)] = typeof(EnumConverter);
  143.                    
  144.                     // Special cases for things that are not bound to a specific type
  145.                     //
  146.                     temp[_intrinsicReferenceKey] = typeof(ReferenceConverter);
  147.                     temp[_intrinsicNullableKey] = typeof(NullableConverter);
  148.                    
  149.                     _intrinsicTypeConverters = temp;
  150.                 }
  151.                 return _intrinsicTypeConverters;
  152.             }
  153.         }
  154.        
  155.         /// <devdoc>
  156.         /// Adds an editor table for the given editor base type.
  157.         /// ypically, editors are specified as metadata on an object. If no metadata for a
  158.         /// equested editor base type can be found on an object, however, the
  159.         /// ypeDescriptor will search an editor
  160.         /// able for the editor type, if one can be found.
  161.         /// </devdoc>
  162.         static internal void AddEditorTable(Type editorBaseType, Hashtable table)
  163.         {
  164.             if (editorBaseType == null) {
  165.                 throw new ArgumentNullException("editorBaseType");
  166.             }
  167.            
  168.             if (table == null) {
  169.                 Debug.Fail("COMPAT: Editor table should not be null");
  170.                 // don't throw; RTM didn't so we can't do it either.
  171.             }
  172.            
  173.             lock (_internalSyncObject) {
  174.                 if (_editorTables == null) {
  175.                     _editorTables = new Hashtable(4);
  176.                 }
  177.                
  178.                 if (!_editorTables.ContainsKey(editorBaseType)) {
  179.                     _editorTables[editorBaseType] = table;
  180.                 }
  181.             }
  182.         }
  183.        
  184.         /// <devdoc>
  185.         /// CreateInstance implementation. We delegate to Activator.
  186.         /// </devdoc>
  187.         public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
  188.         {
  189.             Debug.Assert(objectType != null, "Should have arg-checked before coming in here");
  190.            
  191.             object obj = null;
  192.            
  193.             if (argTypes != null) {
  194.                 obj = SecurityUtils.SecureConstructorInvoke(objectType, argTypes, args, true, BindingFlags.ExactBinding);
  195.             }
  196.             else {
  197.                 if (args != null) {
  198.                     argTypes = new Type[args.Length];
  199.                     for (int idx = 0; idx < args.Length; idx++) {
  200.                         if (args[idx] != null) {
  201.                             argTypes[idx] = args[idx].GetType();
  202.                         }
  203.                         else {
  204.                             argTypes[idx] = typeof(object);
  205.                         }
  206.                     }
  207.                 }
  208.                 else {
  209.                     argTypes = new Type[0];
  210.                 }
  211.                
  212.                 obj = SecurityUtils.SecureConstructorInvoke(objectType, argTypes, args, true);
  213.             }
  214.            
  215.             if (obj == null) {
  216.                 obj = SecurityUtils.SecureCreateInstance(objectType, args);
  217.             }
  218.            
  219.             return obj;
  220.         }
  221.        
  222.        
  223.         /// <devdoc>
  224.         /// Helper method to create editors and type converters. This checks to see if the
  225.         /// type implements a Type constructor, and if it does it invokes that ctor.
  226.         /// Otherwise, it just tries to create the type.
  227.         /// </devdoc>
  228.         private static object CreateInstance(Type objectType, Type callingType)
  229.         {
  230.             object obj = SecurityUtils.SecureConstructorInvoke(objectType, _typeConstructor, new object[] {callingType}, false);
  231.            
  232.             if (obj == null) {
  233.                 obj = SecurityUtils.SecureCreateInstance(objectType);
  234.             }
  235.            
  236.             return obj;
  237.         }
  238.        
  239.         /// <devdoc>
  240.         /// Retrieves custom attributes.
  241.         /// </devdoc>
  242.         internal AttributeCollection GetAttributes(Type type)
  243.         {
  244.             ReflectedTypeData td = GetTypeData(type, true);
  245.             return td.GetAttributes();
  246.         }
  247.        
  248.         /// <devdoc>
  249.         /// Our implementation of GetCache sits on top of IDictionaryService.
  250.         /// </devdoc>
  251.         public override IDictionary GetCache(object instance)
  252.         {
  253.             IComponent comp = instance as IComponent;
  254.             if (comp != null && comp.Site != null) {
  255.                 IDictionaryService ds = comp.Site.GetService(typeof(IDictionaryService)) as IDictionaryService;
  256.                 if (ds != null) {
  257.                     IDictionary dict = ds.GetValue(_dictionaryKey) as IDictionary;
  258.                     if (dict == null) {
  259.                         dict = new Hashtable();
  260.                         ds.SetValue(_dictionaryKey, dict);
  261.                     }
  262.                     return dict;
  263.                 }
  264.             }
  265.            
  266.             return null;
  267.         }
  268.        
  269.         /// <devdoc>
  270.         /// Retrieves the class name for our type.
  271.         /// </devdoc>
  272.         internal string GetClassName(Type type)
  273.         {
  274.             ReflectedTypeData td = GetTypeData(type, true);
  275.             return td.GetClassName(null);
  276.         }
  277.        
  278.         /// <devdoc>
  279.         /// Retrieves the component name from the site.
  280.         /// </devdoc>
  281.         internal string GetComponentName(Type type, object instance)
  282.         {
  283.             ReflectedTypeData td = GetTypeData(type, true);
  284.             return td.GetComponentName(instance);
  285.         }
  286.        
  287.         /// <devdoc>
  288.         /// Retrieves the type converter. If instance is non-null,
  289.         /// it will be used to retrieve attributes. Otherwise, _type
  290.         /// will be used.
  291.         /// </devdoc>
  292.         internal TypeConverter GetConverter(Type type, object instance)
  293.         {
  294.             ReflectedTypeData td = GetTypeData(type, true);
  295.             return td.GetConverter(instance);
  296.         }
  297.        
  298.         /// <devdoc>
  299.         /// Return the default event. The default event is determined by the
  300.         /// presence of a DefaultEventAttribute on the class.
  301.         /// </devdoc>
  302.         internal EventDescriptor GetDefaultEvent(Type type, object instance)
  303.         {
  304.             ReflectedTypeData td = GetTypeData(type, true);
  305.             return td.GetDefaultEvent(instance);
  306.         }
  307.        
  308.         /// <devdoc>
  309.         /// Return the default property.
  310.         /// </devdoc>
  311.         internal PropertyDescriptor GetDefaultProperty(Type type, object instance)
  312.         {
  313.             ReflectedTypeData td = GetTypeData(type, true);
  314.             return td.GetDefaultProperty(instance);
  315.         }
  316.        
  317.         /// <devdoc>
  318.         /// Retrieves the editor for the given base type.
  319.         /// </devdoc>
  320.         internal object GetEditor(Type type, object instance, Type editorBaseType)
  321.         {
  322.             ReflectedTypeData td = GetTypeData(type, true);
  323.             return td.GetEditor(instance, editorBaseType);
  324.         }
  325.        
  326.         /// <devdoc>
  327.         /// Retrieves a default editor table for the given editor base type.
  328.         /// </devdoc>
  329.         private static Hashtable GetEditorTable(Type editorBaseType)
  330.         {
  331.            
  332.             if (_editorTables == null) {
  333.                 lock (_internalSyncObject) {
  334.                     if (_editorTables == null) {
  335.                         _editorTables = new Hashtable(4);
  336.                     }
  337.                 }
  338.             }
  339.            
  340.             object table = _editorTables[editorBaseType];
  341.            
  342.             if (table == null) {
  343.                 // Before we give up, it is possible that the
  344.                 // class initializer for editorBaseType hasn't
  345.                 // actually run.
  346.                 //
  347.                 System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(editorBaseType.TypeHandle);
  348.                 table = _editorTables[editorBaseType];
  349.                
  350.                 // If the table is still null, then throw a
  351.                 // sentinel in there so we don't
  352.                 // go through this again.
  353.                 //
  354.                 if (table == null) {
  355.                     lock (_internalSyncObject) {
  356.                         table = _editorTables[editorBaseType];
  357.                         if (table == null) {
  358.                             _editorTables[editorBaseType] = _editorTables;
  359.                         }
  360.                     }
  361.                 }
  362.             }
  363.            
  364.             // Look for our sentinel value that indicates
  365.             // we have already tried and failed to get
  366.             // a table.
  367.             //
  368.             if (table == _editorTables) {
  369.                 table = null;
  370.             }
  371.            
  372.             return (Hashtable)table;
  373.         }
  374.        
  375.         /// <devdoc>
  376.         /// Retrieves the events for this type.
  377.         /// </devdoc>
  378.         internal EventDescriptorCollection GetEvents(Type type)
  379.         {
  380.             ReflectedTypeData td = GetTypeData(type, true);
  381.             return td.GetEvents();
  382.         }
  383.        
  384.         /// <devdoc>
  385.         /// Retrieves custom extender attributes. We don't support
  386.         /// extender attributes, so we always return an empty collection.
  387.         /// </devdoc>
  388.         internal AttributeCollection GetExtendedAttributes(object instance)
  389.         {
  390.             return AttributeCollection.Empty;
  391.         }
  392.        
  393.         /// <devdoc>
  394.         /// Retrieves the class name for our type.
  395.         /// </devdoc>
  396.         internal string GetExtendedClassName(object instance)
  397.         {
  398.             return GetClassName(instance.GetType());
  399.         }
  400.        
  401.         /// <devdoc>
  402.         /// Retrieves the component name from the site.
  403.         /// </devdoc>
  404.         internal string GetExtendedComponentName(object instance)
  405.         {
  406.             return GetComponentName(instance.GetType(), instance);
  407.         }
  408.        
  409.         /// <devdoc>
  410.         /// Retrieves the type converter. If instance is non-null,
  411.         /// it will be used to retrieve attributes. Otherwise, _type
  412.         /// will be used.
  413.         /// </devdoc>
  414.         internal TypeConverter GetExtendedConverter(object instance)
  415.         {
  416.             return GetConverter(instance.GetType(), instance);
  417.         }
  418.        
  419.         /// <devdoc>
  420.         /// Return the default event. The default event is determined by the
  421.         /// presence of a DefaultEventAttribute on the class.
  422.         /// </devdoc>
  423.         internal EventDescriptor GetExtendedDefaultEvent(object instance)
  424.         {
  425.             return null;
  426.             // we don't support extended events.
  427.         }
  428.        
  429.         /// <devdoc>
  430.         /// Return the default property.
  431.         /// </devdoc>
  432.         internal PropertyDescriptor GetExtendedDefaultProperty(object instance)
  433.         {
  434.             return null;
  435.             // extender properties are never the default.
  436.         }
  437.        
  438.         /// <devdoc>
  439.         /// Retrieves the editor for the given base type.
  440.         /// </devdoc>
  441.         internal object GetExtendedEditor(object instance, Type editorBaseType)
  442.         {
  443.             return GetEditor(instance.GetType(), instance, editorBaseType);
  444.         }
  445.        
  446.         /// <devdoc>
  447.         /// Retrieves the events for this type.
  448.         /// </devdoc>
  449.         internal EventDescriptorCollection GetExtendedEvents(object instance)
  450.         {
  451.             return EventDescriptorCollection.Empty;
  452.         }
  453.        
  454.         /// <devdoc>
  455.         /// Retrieves the properties for this type.
  456.         /// </devdoc>
  457.         internal PropertyDescriptorCollection GetExtendedProperties(object instance)
  458.         {
  459.             // Is this object a sited component? If not, then it
  460.             // doesn't have any extender properties.
  461.             //
  462.             Type componentType = instance.GetType();
  463.             IComponent component = instance as IComponent;
  464.             if (component == null || component.Site == null) {
  465.                 return PropertyDescriptorCollection.Empty;
  466.             }
  467.            
  468.             // Check the component for extender providers. We prefer
  469.             // IExtenderListService, but will use the container if that's
  470.             // all we have. In either case, we check the list of extenders
  471.             // against previously stored data in the object cache. If
  472.             // the cache is up to date, we just return the extenders in the
  473.             // cache.
  474.             //
  475.             IExtenderProvider[] extenders = null;
  476.             IExtenderListService extenderList = component.Site.GetService(typeof(IExtenderListService)) as IExtenderListService;
  477.             IDictionary cache = TypeDescriptor.GetCache(instance);
  478.            
  479.             if (extenderList != null) {
  480.                 extenders = GetExtenders(extenderList.GetExtenderProviders(), instance, cache);
  481.             }
  482.             else {
  483.                 IContainer cont = component.Site.Container;
  484.                 if (cont != null) {
  485.                     extenders = GetExtenders(cont.Components, instance, cache);
  486.                 }
  487.             }
  488.            
  489.             if (extenders == null) {
  490.                 return PropertyDescriptorCollection.Empty;
  491.             }
  492.            
  493.             // Ok, we have a set of extenders. Now, check to see if there
  494.             // are properties already in our object cache. If there aren't,
  495.             // then we will need to create them.
  496.             //
  497.             PropertyDescriptorCollection properties = null;
  498.            
  499.             if (cache != null) {
  500.                 properties = cache[_extenderPropertiesKey] as PropertyDescriptorCollection;
  501.             }
  502.            
  503.             if (properties != null) {
  504.                 return properties;
  505.             }
  506.            
  507.             // Unlike normal properties, it is fine for there to be properties with
  508.             // duplicate names here.
  509.             //
  510.             ArrayList propertyList = null;
  511.            
  512.             for (int idx = 0; idx < extenders.Length; idx++) {
  513.                 PropertyDescriptor[] propertyArray = ReflectGetExtendedProperties(extenders[idx]);
  514.                
  515.                 if (propertyList == null) {
  516.                     propertyList = new ArrayList(propertyArray.Length * extenders.Length);
  517.                 }
  518.                
  519.                 for (int propIdx = 0; propIdx < propertyArray.Length; propIdx++) {
  520.                     PropertyDescriptor prop = propertyArray[propIdx];
  521.                     ExtenderProvidedPropertyAttribute eppa = prop.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute;
  522.                    
  523.                     Debug.Assert(eppa != null, "Extender property " + prop.Name + " has no provider attribute. We will skip it.");
  524.                     if (eppa != null) {
  525.                         Type receiverType = eppa.ReceiverType;
  526.                         if (receiverType != null) {
  527.                            
  528.                             if (receiverType.IsAssignableFrom(componentType)) {
  529.                                 propertyList.Add(prop);
  530.                             }
  531.                         }
  532.                     }
  533.                 }
  534.             }
  535.            
  536.             // propertyHash now contains ExtendedPropertyDescriptor objects
  537.             // for each extended property.
  538.             //
  539.             if (propertyList != null) {
  540.                 TypeDescriptor.Trace("Extenders : Allocating property collection for {0} properties", propertyList.Count);
  541.                 PropertyDescriptor[] fullArray = new PropertyDescriptor[propertyList.Count];
  542.                 propertyList.CopyTo(fullArray, 0);
  543.                 properties = new PropertyDescriptorCollection(fullArray, true);
  544.             }
  545.             else {
  546.                 properties = PropertyDescriptorCollection.Empty;
  547.             }
  548.            
  549.             if (cache != null) {
  550.                 TypeDescriptor.Trace("Extenders : caching extender results");
  551.                 cache[_extenderPropertiesKey] = properties;
  552.             }
  553.            
  554.             return properties;
  555.         }
  556.        
  557.         /// <devdoc>
  558.         /// GetExtenders builds a list of extender providers from
  559.         /// a collection of components. It validates the extenders
  560.         /// against any cached collection of extenders in the
  561.         /// cache. If there is a discrepancy, this will erase
  562.         /// any cached extender properties from the cache and
  563.         /// save the updated extender list. If there is no
  564.         /// discrepancy this will simply return the cached list.
  565.         /// </devdoc>
  566.         private static IExtenderProvider[] GetExtenders(ICollection components, object instance, IDictionary cache)
  567.         {
  568.             bool newExtenders = false;
  569.             int extenderCount = 0;
  570.             IExtenderProvider[] existingExtenders = null;
  571.            
  572.             //CanExtend is expensive. We will remember results of CanExtend for the first 64 extenders and using "long canExtend" as a bit vector.
  573.             // we want to avoid memory allocation as well so we don't use some more sophisticated data structure like an array of booleans
  574.             UInt64 canExtend = 0;
  575.             int maxCanExtendResults = 64;
  576.             // currentExtenders is what we intend to return. If the caller passed us
  577.             // the return value from IExtenderListService, components will already be
  578.             // an IExtenderProvider[]. If not, then we must treat components as an
  579.             // opaque collection. We spend a great deal of energy here to avoid
  580.             // copying or allocating memory because this method is called every
  581.             // time a component is asked for its properties.
  582.             IExtenderProvider[] currentExtenders = components as IExtenderProvider[];
  583.            
  584.             if (cache != null) {
  585.                 existingExtenders = cache[_extenderProviderKey] as IExtenderProvider[];
  586.             }
  587.            
  588.             if (existingExtenders == null) {
  589.                 newExtenders = true;
  590.             }
  591.            
  592.             int curIdx = 0;
  593.             int idx = 0;
  594.            
  595.             if (currentExtenders != null) {
  596.                 for (curIdx = 0; curIdx < currentExtenders.Length; curIdx++) {
  597.                     if (currentExtenders[curIdx].CanExtend(instance)) {
  598.                         extenderCount++;
  599.                         // Performance:We would like to call CanExtend as little as possible therefore we remember its result
  600.                         if (curIdx < maxCanExtendResults)
  601.                             canExtend |= (UInt64)1 << curIdx;
  602.                         if (!newExtenders && (idx >= existingExtenders.Length || currentExtenders[curIdx] != existingExtenders[idx++])) {
  603.                             newExtenders = true;
  604.                         }
  605.                     }
  606.                 }
  607.             }
  608.             else if (components != null) {
  609.                 foreach (object obj in components) {
  610.                     IExtenderProvider prov = obj as IExtenderProvider;
  611.                     if (prov != null && prov.CanExtend(instance)) {
  612.                         extenderCount++;
  613.                         if (curIdx < maxCanExtendResults)
  614.                             canExtend |= (UInt64)1 << curIdx;
  615.                         if (!newExtenders && (idx >= existingExtenders.Length || prov != existingExtenders[idx++])) {
  616.                             newExtenders = true;
  617.                         }
  618.                     }
  619.                     curIdx++;
  620.                 }
  621.             }
  622.             if (existingExtenders != null && extenderCount != existingExtenders.Length) {
  623.                 newExtenders = true;
  624.             }
  625.             if (newExtenders) {
  626.                 TypeDescriptor.Trace("Extenders : object has new extenders : {0}", instance.GetType().Name);
  627.                 TypeDescriptor.Trace("Extenders : Identified {0} extender providers", extenderCount);
  628.                 if (currentExtenders == null || extenderCount != currentExtenders.Length) {
  629.                     IExtenderProvider[] newExtenderArray = new IExtenderProvider[extenderCount];
  630.                    
  631.                     curIdx = 0;
  632.                     idx = 0;
  633.                    
  634.                     if (currentExtenders != null && extenderCount > 0) {
  635.                         while (curIdx < currentExtenders.Length) {
  636.                             if ((curIdx < maxCanExtendResults && (canExtend & ((UInt64)1 << curIdx)) != 0) || (curIdx >= maxCanExtendResults && currentExtenders[curIdx].CanExtend(instance))) {
  637.                                 Debug.Assert(idx < extenderCount, "There are more extenders than we expect");
  638.                                 newExtenderArray[idx++] = currentExtenders[curIdx];
  639.                             }
  640.                             curIdx++;
  641.                         }
  642.                         Debug.Assert(idx == extenderCount, "Wrong number of extenders");
  643.                     }
  644.                     else if (extenderCount > 0) {
  645.                         IEnumerator componentEnum = components.GetEnumerator();
  646.                         while (componentEnum.MoveNext()) {
  647.                             IExtenderProvider p = componentEnum.Current as IExtenderProvider;
  648.                            
  649.                             if (p != null && ((curIdx < maxCanExtendResults && (canExtend & ((UInt64)1 << curIdx)) != 0) || (curIdx >= maxCanExtendResults && p.CanExtend(instance)))) {
  650.                                 Debug.Assert(idx < extenderCount, "There are more extenders than we expect");
  651.                                 newExtenderArray[idx++] = p;
  652.                             }
  653.                             curIdx++;
  654.                         }
  655.                         Debug.Assert(idx == extenderCount, "Wrong number of extenders");
  656.                     }
  657.                     currentExtenders = newExtenderArray;
  658.                 }
  659.                
  660.                 if (cache != null) {
  661.                     TypeDescriptor.Trace("Extenders : caching extender provider results");
  662.                     cache[_extenderProviderKey] = currentExtenders;
  663.                     cache.Remove(_extenderPropertiesKey);
  664.                 }
  665.             }
  666.             else {
  667.                 currentExtenders = existingExtenders;
  668.             }
  669.             return currentExtenders;
  670.         }
  671.        
  672.         /// <devdoc>
  673.         /// Retrieves the owner for a property.
  674.         /// </devdoc>
  675.         internal object GetExtendedPropertyOwner(object instance, PropertyDescriptor pd)
  676.         {
  677.             return GetPropertyOwner(instance.GetType(), instance, pd);
  678.         }
  679.        
  680.         //////////////////////////////////////////////////////////
  681.         /// <devdoc>
  682.         /// Provides a type descriptor for the given object. We only support this
  683.         /// if the object is a component that
  684.         /// </devdoc>
  685.         public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
  686.         {
  687.             Debug.Fail("This should never be invoked. TypeDescriptionNode should wrap for us.");
  688.             return null;
  689.         }
  690.        
  691.         /// <devdoc>
  692.         /// The name of the specified component, or null if the component has no name.
  693.         /// In many cases this will return the same value as GetComponentName. If the
  694.         /// component resides in a nested container or has other nested semantics, it may
  695.         /// return a different fully qualfied name.
  696.         ///
  697.         /// If not overridden, the default implementation of this method will call
  698.         /// GetComponentName.
  699.         /// </devdoc>
  700.         public override string GetFullComponentName(object component)
  701.         {
  702.             IComponent comp = component as IComponent;
  703.             if (comp != null) {
  704.                 INestedSite ns = comp.Site as INestedSite;
  705.                 if (ns != null) {
  706.                     return ns.FullName;
  707.                 }
  708.             }
  709.            
  710.             return TypeDescriptor.GetComponentName(component);
  711.         }
  712.        
  713.         /// <devdoc>
  714.         /// Returns an array of types we have populated metadata for that live
  715.         /// in the current module.
  716.         /// </devdoc>
  717.         internal Type[] GetPopulatedTypes(Module module)
  718.         {
  719.             ArrayList typeList = new ArrayList();
  720.             ;
  721.            
  722.             foreach (DictionaryEntry de in _typeData) {
  723.                 Type type = (Type)de.Key;
  724.                 ReflectedTypeData typeData = (ReflectedTypeData)de.Value;
  725.                
  726.                 if (type.Module == module && typeData.IsPopulated) {
  727.                     typeList.Add(type);
  728.                 }
  729.             }
  730.            
  731.             return (Type[])typeList.ToArray(typeof(Type));
  732.         }
  733.        
  734.         /// <devdoc>
  735.         /// Retrieves the properties for this type.
  736.         /// </devdoc>
  737.         internal PropertyDescriptorCollection GetProperties(Type type)
  738.         {
  739.             ReflectedTypeData td = GetTypeData(type, true);
  740.             return td.GetProperties();
  741.         }
  742.        
  743.         /// <devdoc>
  744.         /// Retrieves the owner for a property.
  745.         /// </devdoc>
  746.         internal object GetPropertyOwner(Type type, object instance, PropertyDescriptor pd)
  747.         {
  748.             return TypeDescriptor.GetAssociation(type, instance);
  749.         }
  750.        
  751.         /// <devdoc>
  752.         /// Returns an Type for the given type. Since type implements IReflect,
  753.         /// we just return objectType.
  754.         /// </devdoc>
  755.         public override Type GetReflectionType(Type objectType, object instance)
  756.         {
  757.             Debug.Assert(objectType != null, "Should have arg-checked before coming in here");
  758.             return objectType;
  759.         }
  760.        
  761.         /// <devdoc>
  762.         /// Returns the type data for the given type, or
  763.         /// null if there is no type data for the type yet and
  764.         /// createIfNeeded is false.
  765.         /// </devdoc>
  766.         private ReflectedTypeData GetTypeData(Type type, bool createIfNeeded)
  767.         {
  768.            
  769.             ReflectedTypeData td = null;
  770.            
  771.             if (_typeData != null) {
  772.                 td = (ReflectedTypeData)_typeData[type];
  773.             }
  774.            
  775.             if (td == null && createIfNeeded) {
  776.                 td = new ReflectedTypeData(type);
  777.                 if (_typeData == null) {
  778.                     _typeData = new Hashtable();
  779.                 }
  780.                 _typeData[type] = td;
  781.             }
  782.            
  783.             return td;
  784.         }
  785.        
  786.         /// <devdoc>
  787.         /// This method returns a custom type descriptor for the given type / object.
  788.         /// The objectType parameter is always valid, but the instance parameter may
  789.         /// be null if no instance was passed to TypeDescriptor. The method should
  790.         /// return a custom type descriptor for the object. If the method is not
  791.         /// interested in providing type information for the object it should
  792.         /// return null.
  793.         /// </devdoc>
  794.         public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
  795.         {
  796.             Debug.Fail("This should never be invoked. TypeDescriptionNode should wrap for us.");
  797.             return null;
  798.         }
  799.        
  800.         /// <devdoc>
  801.         /// Retrieves a type from a name.
  802.         /// </devdoc>
  803.         private static Type GetTypeFromName(string typeName)
  804.         {
  805.             Type t = Type.GetType(typeName);
  806.            
  807.             if (t == null) {
  808.                 int commaIndex = typeName.IndexOf(',');
  809.                
  810.                 if (commaIndex != -1) {
  811.                     // At design time, it's possible for us to reuse
  812.                     // an assembly but add new types. The app domain
  813.                     // will cache the assembly based on identity, however,
  814.                     // so it could be looking in the previous version
  815.                     // of the assembly and not finding the type. We work
  816.                     // around this by looking for the non-assembly qualified
  817.                     // name, which causes the domain to raise a type
  818.                     // resolve event.
  819.                     //
  820.                     t = Type.GetType(typeName.Substring(0, commaIndex));
  821.                 }
  822.             }
  823.            
  824.             return t;
  825.         }
  826.        
  827.         /// <devdoc>
  828.         /// This method returns true if the data cache in this reflection
  829.         /// type descriptor has data in it.
  830.         /// </devdoc>
  831.         internal bool IsPopulated(Type type)
  832.         {
  833.             ReflectedTypeData td = GetTypeData(type, false);
  834.             if (td != null) {
  835.                 return td.IsPopulated;
  836.             }
  837.             return false;
  838.         }
  839.        
  840.         /// <devdoc>
  841.         /// Static helper API around reflection to get and cache
  842.         /// custom attributes. This does not recurse, but it will
  843.         /// walk interfaces on the type. Interfaces are added
  844.         /// to the end, so merging should be done from length - 1
  845.         /// to 0.
  846.         /// </devdoc>
  847.         private static Attribute[] ReflectGetAttributes(Type type)
  848.         {
  849.             if (_attributeCache == null) {
  850.                 lock (_internalSyncObject) {
  851.                     if (_attributeCache == null) {
  852.                         _attributeCache = new Hashtable();
  853.                     }
  854.                 }
  855.             }
  856.            
  857.             Attribute[] attrs = (Attribute[])_attributeCache[type];
  858.             if (attrs == null) {
  859.                 TypeDescriptor.Trace("Attributes : Building attributes for {0}", type.Name);
  860.                
  861.                 // Get the type's attributes.
  862.                 //
  863.                 object[] typeAttrs = type.GetCustomAttributes(typeof(Attribute), false);
  864.                
  865.                 attrs = new Attribute[typeAttrs.Length];
  866.                 typeAttrs.CopyTo(attrs, 0);
  867.                
  868.                 _attributeCache[type] = attrs;
  869.             }
  870.            
  871.             return attrs;
  872.         }
  873.        
  874.         /// <devdoc>
  875.         /// Static helper API around reflection to get and cache
  876.         /// custom attributes. This does not recurse to the base class.
  877.         /// </devdoc>
  878.         static internal Attribute[] ReflectGetAttributes(MemberInfo member)
  879.         {
  880.             if (_attributeCache == null) {
  881.                 lock (_internalSyncObject) {
  882.                     if (_attributeCache == null) {
  883.                         _attributeCache = new Hashtable();
  884.                     }
  885.                 }
  886.             }
  887.            
  888.             Attribute[] attrs = (Attribute[])_attributeCache[member];
  889.             if (attrs == null) {
  890.                 // Get the member's attributes.
  891.                 //
  892.                 object[] memberAttrs = member.GetCustomAttributes(typeof(Attribute), false);
  893.                 attrs = new Attribute[memberAttrs.Length];
  894.                 memberAttrs.CopyTo(attrs, 0);
  895.                 _attributeCache[member] = attrs;
  896.             }
  897.            
  898.             return attrs;
  899.         }
  900.        
  901.         /// <devdoc>
  902.         /// Static helper API around reflection to get and cache
  903.         /// events. This does not recurse to the base class.
  904.         /// </devdoc>
  905.         private static EventDescriptor[] ReflectGetEvents(Type type)
  906.         {
  907.             if (_eventCache == null) {
  908.                 lock (_internalSyncObject) {
  909.                     if (_eventCache == null) {
  910.                         _eventCache = new Hashtable();
  911.                     }
  912.                 }
  913.             }
  914.            
  915.             EventDescriptor[] events = (EventDescriptor[])_eventCache[type];
  916.             if (events == null) {
  917.                 BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
  918.                 TypeDescriptor.Trace("Events : Building events for {0}", type.Name);
  919.                
  920.                 // Get the type's events. Events may have their add and
  921.                 // remove methods individually overridden in a derived
  922.                 // class, but at some point in the base class chain both
  923.                 // methods must exist. If we find an event that doesn't
  924.                 // have both add and remove, we skip it here, because it
  925.                 // will be picked up in our base class scan.
  926.                 //
  927.                 EventInfo[] eventInfos = type.GetEvents(bindingFlags);
  928.                 events = new EventDescriptor[eventInfos.Length];
  929.                 int eventCount = 0;
  930.                
  931.                 for (int idx = 0; idx < eventInfos.Length; idx++) {
  932.                     EventInfo eventInfo = eventInfos[idx];
  933.                    
  934.                     if ((!(eventInfo.DeclaringType.IsPublic || eventInfo.DeclaringType.IsNestedPublic)) && (eventInfo.DeclaringType.Assembly == typeof(ReflectTypeDescriptionProvider).Assembly)) {
  935.                         Debug.Fail("Hey, assumption holds true. Rip this assert.");
  936.                         continue;
  937.                     }
  938.                    
  939.                     MethodInfo addMethod = eventInfo.GetAddMethod();
  940.                     MethodInfo removeMethod = eventInfo.GetRemoveMethod();
  941.                    
  942.                     if (addMethod != null && removeMethod != null) {
  943.                         events[eventCount++] = new ReflectEventDescriptor(type, eventInfo);
  944.                     }
  945.                 }
  946.                
  947.                 if (eventCount != events.Length) {
  948.                     EventDescriptor[] newEvents = new EventDescriptor[eventCount];
  949.                     Array.Copy(events, 0, newEvents, 0, eventCount);
  950.                     events = newEvents;
  951.                 }
  952.                
  953.                 #if DEBUG
  954.                 foreach (EventDescriptor dbgEvent in events) {
  955.                     Debug.Assert(dbgEvent != null, "Holes in event array for type " + type);
  956.                 }
  957.                 #endif
  958.                 _eventCache[type] = events;
  959.             }
  960.            
  961.             return events;
  962.         }
  963.        
  964.         /// <devdoc>
  965.         /// This performs the actual reflection needed to discover
  966.         /// extender properties. If object caching is supported this
  967.         /// will maintain a cache of property descriptors on the
  968.         /// extender provider. Extender properties are actually two
  969.         /// property descriptors in one. There is a chunk of per-class
  970.         /// data in a ReflectPropertyDescriptor that defines the
  971.         /// parameter types and get and set methods of the extended property,
  972.         /// and there is an ExtendedPropertyDescriptor that combines this
  973.         /// with an extender provider object to create what looks like a
  974.         /// normal property. ReflectGetExtendedProperties maintains two
  975.         /// separate caches for these two sets: a static one for the
  976.         /// ReflectPropertyDescriptor values that don't change for each
  977.         /// provider instance, and a per-provider cache that contains
  978.         /// the ExtendedPropertyDescriptors.
  979.         /// </devdoc>
  980.         private static PropertyDescriptor[] ReflectGetExtendedProperties(IExtenderProvider provider)
  981.         {
  982.             IDictionary cache = TypeDescriptor.GetCache(provider);
  983.             PropertyDescriptor[] properties;
  984.            
  985.             if (cache != null) {
  986.                 properties = cache[_extenderProviderPropertiesKey] as PropertyDescriptor[];
  987.                 if (properties != null) {
  988.                     return properties;
  989.                 }
  990.             }
  991.            
  992.             // Our per-instance cache missed. We have never seen this instance of the
  993.             // extender provider before. See if we can find our class-based
  994.             // property store.
  995.             //
  996.             if (_extendedPropertyCache == null) {
  997.                 lock (_internalSyncObject) {
  998.                     if (_extendedPropertyCache == null) {
  999.                         _extendedPropertyCache = new Hashtable();
  1000.                     }
  1001.                 }
  1002.             }
  1003.            
  1004.             Type providerType = provider.GetType();
  1005.             ReflectPropertyDescriptor[] extendedProperties = (ReflectPropertyDescriptor[])_extendedPropertyCache[providerType];
  1006.            
  1007.             // Our class-based property store failed as well, so we need to build up the set of
  1008.             // extended properties here.
  1009.             //
  1010.             if (extendedProperties == null) {
  1011.                 AttributeCollection attributes = TypeDescriptor.GetAttributes(providerType);
  1012.                 ArrayList extendedList = new ArrayList(attributes.Count);
  1013.                
  1014.                 foreach (Attribute attr in attributes) {
  1015.                     ProvidePropertyAttribute provideAttr = attr as ProvidePropertyAttribute;
  1016.                    
  1017.                     if (provideAttr != null) {
  1018.                         Type receiverType = GetTypeFromName(provideAttr.ReceiverTypeName);
  1019.                        
  1020.                         if (receiverType != null) {
  1021.                             MethodInfo getMethod = providerType.GetMethod("Get" + provideAttr.PropertyName, new Type[] {receiverType});
  1022.                            
  1023.                             if (getMethod != null && !getMethod.IsStatic && getMethod.IsPublic) {
  1024.                                 MethodInfo setMethod = providerType.GetMethod("Set" + provideAttr.PropertyName, new Type[] {receiverType, getMethod.ReturnType});
  1025.                                
  1026.                                 if (setMethod != null && (setMethod.IsStatic || !setMethod.IsPublic)) {
  1027.                                     setMethod = null;
  1028.                                 }
  1029.                                
  1030.                                 extendedList.Add(new ReflectPropertyDescriptor(providerType, provideAttr.PropertyName, getMethod.ReturnType, receiverType, getMethod, setMethod, null));
  1031.                             }
  1032.                         }
  1033.                     }
  1034.                 }
  1035.                
  1036.                 extendedProperties = new ReflectPropertyDescriptor[extendedList.Count];
  1037.                 extendedList.CopyTo(extendedProperties, 0);
  1038.                 _extendedPropertyCache[providerType] = extendedProperties;
  1039.             }
  1040.            
  1041.             // Now that we have our extended properties we can build up a list of callable properties. These can be
  1042.             // returned to the user.
  1043.             //
  1044.             properties = new PropertyDescriptor[extendedProperties.Length];
  1045.             for (int idx = 0; idx < extendedProperties.Length; idx++) {
  1046.                 Attribute[] attrs = null;
  1047.                 IComponent comp = provider as IComponent;
  1048.                 if (comp == null || comp.Site == null) {
  1049.                     attrs = new Attribute[] {DesignOnlyAttribute.Yes};
  1050.                 }
  1051.                
  1052.                 ReflectPropertyDescriptor rpd = extendedProperties[idx];
  1053.                 ExtendedPropertyDescriptor epd = new ExtendedPropertyDescriptor(rpd, rpd.ExtenderGetReceiverType(), provider, attrs);
  1054.                 properties[idx] = epd;
  1055.             }
  1056.            
  1057.             if (cache != null) {
  1058.                 cache[_extenderProviderPropertiesKey] = properties;
  1059.             }
  1060.            
  1061.             return properties;
  1062.         }
  1063.        
  1064.         /// <devdoc>
  1065.         /// Static helper API around reflection to get and cache
  1066.         /// properties. This does not recurse to the base class.
  1067.         /// </devdoc>
  1068.         private static PropertyDescriptor[] ReflectGetProperties(Type type)
  1069.         {
  1070.             if (_propertyCache == null) {
  1071.                 lock (_internalSyncObject) {
  1072.                     if (_propertyCache == null) {
  1073.                         _propertyCache = new Hashtable();
  1074.                     }
  1075.                 }
  1076.             }
  1077.            
  1078.             PropertyDescriptor[] properties = (PropertyDescriptor[])_propertyCache[type];
  1079.             if (properties == null) {
  1080.                 BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
  1081.                 TypeDescriptor.Trace("Properties : Building properties for {0}", type.Name);
  1082.                
  1083.                 // Get the type's properties. Properties may have their
  1084.                 // get and set methods individually overridden in a derived
  1085.                 // class, so if we find a missing method we need to walk
  1086.                 // down the base class chain to find it. We actually merge
  1087.                 // "new" properties of the same name, so we must preserve
  1088.                 // the member info for each method individually.
  1089.                 //
  1090.                 PropertyInfo[] propertyInfos = type.GetProperties(bindingFlags);
  1091.                 properties = new PropertyDescriptor[propertyInfos.Length];
  1092.                 int propertyCount = 0;
  1093.                
  1094.                
  1095.                 for (int idx = 0; idx < propertyInfos.Length; idx++) {
  1096.                     PropertyInfo propertyInfo = propertyInfos[idx];
  1097.                    
  1098.                     if (propertyInfo.GetIndexParameters().Length > 0) {
  1099.                         continue;
  1100.                     }
  1101.                    
  1102.                     MethodInfo getMethod = propertyInfo.GetGetMethod();
  1103.                     MethodInfo setMethod = propertyInfo.GetSetMethod();
  1104.                     string name = propertyInfo.Name;
  1105.                    
  1106.                    
  1107.                    
  1108.                     if (getMethod != null) {
  1109.                         properties[propertyCount++] = new ReflectPropertyDescriptor(type, name, propertyInfo.PropertyType, propertyInfo, getMethod, setMethod, null);
  1110.                     }
  1111.                 }
  1112.                
  1113.                
  1114.                 if (propertyCount != properties.Length) {
  1115.                     PropertyDescriptor[] newProperties = new PropertyDescriptor[propertyCount];
  1116.                     Array.Copy(properties, 0, newProperties, 0, propertyCount);
  1117.                     properties = newProperties;
  1118.                 }
  1119.                
  1120.                 #if DEBUG
  1121.                 foreach (PropertyDescriptor dbgProp in properties) {
  1122.                     Debug.Assert(dbgProp != null, "Holes in property array for type " + type);
  1123.                 }
  1124.                 #endif
  1125.                 _propertyCache[type] = properties;
  1126.             }
  1127.            
  1128.             return properties;
  1129.         }
  1130.        
  1131.         /// <devdoc>
  1132.         /// Refreshes the contents of this type descriptor. This does not
  1133.         /// actually requery, but it will clear our state so the next
  1134.         /// query re-populates.
  1135.         /// </devdoc>
  1136.         internal void Refresh(Type type)
  1137.         {
  1138.             ReflectedTypeData td = GetTypeData(type, false);
  1139.             if (td != null) {
  1140.                 td.Refresh();
  1141.             }
  1142.         }
  1143.        
  1144.         /// <devdoc>
  1145.         /// Searches the provided intrinsic hashtable for a match with the object type.
  1146.         /// At the beginning, the hashtable contains types for the various converters.
  1147.         /// As this table is searched, the types for these objects
  1148.         /// are replaced with instances, so we only create as needed. This method
  1149.         /// does the search up the base class hierarchy and will create instances
  1150.         /// for types as needed. These instances are stored back into the table
  1151.         /// for the base type, and for the original component type, for fast access.
  1152.         /// </devdoc>
  1153.         private static object SearchIntrinsicTable(Hashtable table, Type callingType)
  1154.         {
  1155.             object hashEntry = null;
  1156.            
  1157.             // We take a lock on this table. Nothing in this code calls out to
  1158.             // other methods that lock, so it should be fairly safe to grab this
  1159.             // lock. Also, this allows multiple intrinsic tables to be searched
  1160.             // at once.
  1161.             //
  1162.             lock (table) {
  1163.                 Type baseType = callingType;
  1164.                 while (baseType != null && baseType != typeof(object)) {
  1165.                     hashEntry = table[baseType];
  1166.                    
  1167.                     // If the entry is a late-bound type, then try to
  1168.                     // resolve it.
  1169.                     //
  1170.                     string typeString = hashEntry as string;
  1171.                     if (typeString != null) {
  1172.                         hashEntry = Type.GetType(typeString);
  1173.                         if (hashEntry != null) {
  1174.                             table[baseType] = hashEntry;
  1175.                         }
  1176.                     }
  1177.                    
  1178.                     if (hashEntry != null) {
  1179.                         break;
  1180.                     }
  1181.                    
  1182.                     baseType = baseType.BaseType;
  1183.                 }
  1184.                
  1185.                 // Now make a scan through each value in the table, looking for interfaces.
  1186.                 // If we find one, see if the object implements the interface.
  1187.                 //
  1188.                 if (hashEntry == null) {
  1189.                    
  1190.                     foreach (DictionaryEntry de in table) {
  1191.                         Type keyType = de.Key as Type;
  1192.                        
  1193.                         if (keyType != null && keyType.IsInterface && keyType.IsAssignableFrom(callingType)) {
  1194.                            
  1195.                             hashEntry = de.Value;
  1196.                             string typeString = hashEntry as string;
  1197.                            
  1198.                             if (typeString != null) {
  1199.                                 hashEntry = Type.GetType(typeString);
  1200.                                 if (hashEntry != null) {
  1201.                                     table[callingType] = hashEntry;
  1202.                                 }
  1203.                             }
  1204.                            
  1205.                             if (hashEntry != null) {
  1206.                                 break;
  1207.                             }
  1208.                         }
  1209.                     }
  1210.                 }
  1211.                
  1212.                 // Special case converters
  1213.                 //
  1214.                 if (hashEntry == null) {
  1215.                     if (callingType.IsGenericType && callingType.GetGenericTypeDefinition() == typeof(Nullable<>)) {
  1216.                         // Check if it is a nullable value
  1217.                         hashEntry = table[_intrinsicNullableKey];
  1218.                     }
  1219.                     else if (callingType.IsInterface) {
  1220.                         // Finally, check to see if the component type is some unknown interface.
  1221.                         // We have a custom converter for that.
  1222.                         hashEntry = table[_intrinsicReferenceKey];
  1223.                     }
  1224.                 }
  1225.                
  1226.                 // Interfaces do not derive from object, so we
  1227.                 // must handle the case of no hash entry here.
  1228.                 //
  1229.                 if (hashEntry == null) {
  1230.                     hashEntry = table[typeof(object)];
  1231.                 }
  1232.                
  1233.                 // If the entry is a type, create an instance of it and then
  1234.                 // replace the entry. This way we only need to create once.
  1235.                 // We can only do this if the object doesn't want a type
  1236.                 // in its constructor.
  1237.                 //
  1238.                 Type type = hashEntry as Type;
  1239.                
  1240.                 if (type != null) {
  1241.                     hashEntry = CreateInstance(type, callingType);
  1242.                     if (type.GetConstructor(_typeConstructor) == null) {
  1243.                         table[callingType] = hashEntry;
  1244.                     }
  1245.                 }
  1246.             }
  1247.            
  1248.             return hashEntry;
  1249.         }
  1250.        
  1251.         /// <devdoc>
  1252.         /// This class contains all the reflection information for a
  1253.         /// given type.
  1254.         /// </devdoc>
  1255.         private class ReflectedTypeData
  1256.         {
  1257.            
  1258.             private Type _type;
  1259.             private AttributeCollection _attributes;
  1260.             private EventDescriptorCollection _events;
  1261.             private PropertyDescriptorCollection _properties;
  1262.             private TypeConverter _converter;
  1263.             private object[] _editors;
  1264.             private Type[] _editorTypes;
  1265.             private int _editorCount;
  1266.            
  1267.             internal ReflectedTypeData(Type type)
  1268.             {
  1269.                 _type = type;
  1270.                 TypeDescriptor.Trace("Reflect : Creating ReflectedTypeData for {0}", type.Name);
  1271.             }
  1272.            
  1273.             /// <devdoc>
  1274.             /// This method returns true if the data cache in this reflection
  1275.             /// type descriptor has data in it.
  1276.             /// </devdoc>
  1277.             internal bool IsPopulated {
  1278.                 get { return (_attributes != null) | (_events != null) | (_properties != null); }
  1279.             }
  1280.            
  1281.             /// <devdoc>
  1282.             /// Retrieves custom attributes.
  1283.             /// </devdoc>
  1284.             internal AttributeCollection GetAttributes()
  1285.             {
  1286.                 // Worst case collision scenario: we don't want the perf hit
  1287.                 // of taking a lock, so if we collide we will query for
  1288.                 // attributes twice. Not a big deal.
  1289.                 //
  1290.                 if (_attributes == null) {
  1291.                     TypeDescriptor.Trace("Attributes : Building collection for {0}", _type.Name);
  1292.                    
  1293.                     //
  1294.                     //
  1295.                     //
  1296.                     //
  1297.                     //
  1298.                    
  1299.                     Attribute[] attrArray = ReflectTypeDescriptionProvider.ReflectGetAttributes(_type);
  1300.                     Type baseType = _type.BaseType;
  1301.                    
  1302.                     while (baseType != null && baseType != typeof(object)) {
  1303.                         Attribute[] baseArray = ReflectTypeDescriptionProvider.ReflectGetAttributes(baseType);
  1304.                         Attribute[] temp = new Attribute[attrArray.Length + baseArray.Length];
  1305.                         Array.Copy(attrArray, 0, temp, 0, attrArray.Length);
  1306.                         Array.Copy(baseArray, 0, temp, attrArray.Length, baseArray.Length);
  1307.                         attrArray = temp;
  1308.                         baseType = baseType.BaseType;
  1309.                     }
  1310.                    
  1311.                     // Next, walk the type's interfaces. We append these to
  1312.                     // the attribute array as well.
  1313.                     //
  1314.                     int ifaceStartIdx = attrArray.Length;
  1315.                     Type[] interfaces = _type.GetInterfaces();
  1316.                     TypeDescriptor.Trace("Attributes : Walking {0} interfaces", interfaces.Length);
  1317.                     for (int idx = 0; idx < interfaces.Length; idx++) {
  1318.                         Type iface = interfaces[idx];
  1319.                        
  1320.                         // only do this for public interfaces.
  1321.                         //
  1322.                         if ((iface.Attributes & (TypeAttributes.Public | TypeAttributes.NestedPublic)) != 0) {
  1323.                             // No need to pass an instance into GetTypeDescriptor here because, if someone provided a custom
  1324.                             // provider based on object, it already would have hit.
  1325.                             AttributeCollection ifaceAttrs = TypeDescriptor.GetAttributes(iface);
  1326.                             if (ifaceAttrs.Count > 0) {
  1327.                                 Attribute[] temp = new Attribute[attrArray.Length + ifaceAttrs.Count];
  1328.                                 Array.Copy(attrArray, 0, temp, 0, attrArray.Length);
  1329.                                 ifaceAttrs.CopyTo(temp, attrArray.Length);
  1330.                                 attrArray = temp;
  1331.                             }
  1332.                         }
  1333.                     }
  1334.                    
  1335.                     // Finally, hash all these attributes up in reverse order.
  1336.                     //
  1337.                     Hashtable attributeHash = new Hashtable(attrArray.Length);
  1338.                    
  1339.                     for (int idx = attrArray.Length - 1; idx >= 0; idx--) {
  1340.                         bool addAttr = true;
  1341.                         if (idx >= ifaceStartIdx) {
  1342.                             for (int ifaceSkipIdx = 0; ifaceSkipIdx < _skipInterfaceAttributeList.Length; ifaceSkipIdx++) {
  1343.                                 if (_skipInterfaceAttributeList[ifaceSkipIdx].IsInstanceOfType(attrArray[idx])) {
  1344.                                     addAttr = false;
  1345.                                     break;
  1346.                                 }
  1347.                             }
  1348.                            
  1349.                         }
  1350.                        
  1351.                         if (addAttr) {
  1352.                             attributeHash[attrArray[idx].TypeId] = attrArray[idx];
  1353.                         }
  1354.                     }
  1355.                    
  1356.                     attrArray = new Attribute[attributeHash.Count];
  1357.                     attributeHash.Values.CopyTo(attrArray, 0);
  1358.                     _attributes = new AttributeCollection(attrArray);
  1359.                 }
  1360.                
  1361.                 return _attributes;
  1362.             }
  1363.            
  1364.             /// <devdoc>
  1365.             /// Retrieves the class name for our type.
  1366.             /// </devdoc>
  1367.             internal string GetClassName(object instance)
  1368.             {
  1369.                 return _type.FullName;
  1370.             }
  1371.            
  1372.             /// <devdoc>
  1373.             /// Retrieves the component name from the site.
  1374.             /// </devdoc>
  1375.             internal string GetComponentName(object instance)
  1376.             {
  1377.                 IComponent comp = instance as IComponent;
  1378.                 if (comp != null) {
  1379.                     ISite site = comp.Site;
  1380.                     if (site != null) {
  1381.                         INestedSite nestedSite = site as INestedSite;
  1382.                         if (nestedSite != null) {
  1383.                             return nestedSite.FullName;
  1384.                         }
  1385.                         else {
  1386.                             return site.Name;
  1387.                         }
  1388.                     }
  1389.                 }
  1390.                
  1391.                 return null;
  1392.             }
  1393.            
  1394.             /// <devdoc>
  1395.             /// Retrieves the type converter. If instance is non-null,
  1396.             /// it will be used to retrieve attributes. Otherwise, _type
  1397.             /// will be used.
  1398.             /// </devdoc>
  1399.             internal TypeConverter GetConverter(object instance)
  1400.             {
  1401.                 TypeConverterAttribute typeAttr = null;
  1402.                
  1403.                 // For instances, the design time object for them may want to redefine the
  1404.                 // attributes. So, we search the attribute here based on the instance. If found,
  1405.                 // we then search on the same attribute based on type. If the two don't match, then
  1406.                 // we cannot cache the value and must re-create every time. It is rare for a designer
  1407.                 // to override these attributes, so we want to be smart here.
  1408.                 //
  1409.                 if (instance != null) {
  1410.                     typeAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(_type)[typeof(TypeConverterAttribute)];
  1411.                     TypeConverterAttribute instanceAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(instance)[typeof(TypeConverterAttribute)];
  1412.                     if (typeAttr != instanceAttr) {
  1413.                         Type converterType = GetTypeFromName(instanceAttr.ConverterTypeName);
  1414.                         if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) {
  1415.                             try {
  1416.                                 IntSecurity.FullReflection.Assert();
  1417.                                 return (TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type);
  1418.                             }
  1419.                             finally {
  1420.                                 CodeAccessPermission.RevertAssert();
  1421.                             }
  1422.                         }
  1423.                     }
  1424.                 }
  1425.                
  1426.                 // If we got here, we return our type-based converter.
  1427.                 //
  1428.                 if (_converter == null) {
  1429.                     TypeDescriptor.Trace("Converters : Building converter for {0}", _type.Name);
  1430.                    
  1431.                     if (typeAttr == null) {
  1432.                         typeAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(_type)[typeof(TypeConverterAttribute)];
  1433.                     }
  1434.                    
  1435.                     if (typeAttr != null) {
  1436.                         Type converterType = GetTypeFromName(typeAttr.ConverterTypeName);
  1437.                         if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) {
  1438.                             try {
  1439.                                 IntSecurity.FullReflection.Assert();
  1440.                                 _converter = (TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type);
  1441.                             }
  1442.                             finally {
  1443.                                 CodeAccessPermission.RevertAssert();
  1444.                             }
  1445.                         }
  1446.                     }
  1447.                    
  1448.                     if (_converter == null) {
  1449.                         // We did not get a converter. Traverse up the base class chain until
  1450.                         // we find one in the stock hashtable.
  1451.                         //
  1452.                         _converter = (TypeConverter)ReflectTypeDescriptionProvider.SearchIntrinsicTable(IntrinsicTypeConverters, _type);
  1453.                         Debug.Assert(_converter != null, "There is no intrinsic setup in the hashtable for the Object type");
  1454.                     }
  1455.                 }
  1456.                
  1457.                 return _converter;
  1458.             }
  1459.            
  1460.             /// <devdoc>
  1461.             /// Return the default event. The default event is determined by the
  1462.             /// presence of a DefaultEventAttribute on the class.
  1463.             /// </devdoc>
  1464.             internal EventDescriptor GetDefaultEvent(object instance)
  1465.             {
  1466.                 AttributeCollection attributes;
  1467.                
  1468.                 if (instance != null) {
  1469.                     attributes = TypeDescriptor.GetAttributes(instance);
  1470.                 }
  1471.                 else {
  1472.                     attributes = TypeDescriptor.GetAttributes(_type);
  1473.                 }
  1474.                
  1475.                 DefaultEventAttribute attr = (DefaultEventAttribute)attributes[typeof(DefaultEventAttribute)];
  1476.                 if (attr != null && attr.Name != null) {
  1477.                     if (instance != null) {
  1478.                         return TypeDescriptor.GetEvents(instance)[attr.Name];
  1479.                     }
  1480.                     else {
  1481.                         return TypeDescriptor.GetEvents(_type)[attr.Name];
  1482.                     }
  1483.                 }
  1484.                
  1485.                 return null;
  1486.             }
  1487.            
  1488.             /// <devdoc>
  1489.             /// Return the default property.
  1490.             /// </devdoc>
  1491.             internal PropertyDescriptor GetDefaultProperty(object instance)
  1492.             {
  1493.                 AttributeCollection attributes;
  1494.                
  1495.                 if (instance != null) {
  1496.                     attributes = TypeDescriptor.GetAttributes(instance);
  1497.                 }
  1498.                 else {
  1499.                     attributes = TypeDescriptor.GetAttributes(_type);
  1500.                 }
  1501.                
  1502.                 DefaultPropertyAttribute attr = (DefaultPropertyAttribute)attributes[typeof(DefaultPropertyAttribute)];
  1503.                 if (attr != null && attr.Name != null) {
  1504.                     if (instance != null) {
  1505.                         return TypeDescriptor.GetProperties(instance)[attr.Name];
  1506.                     }
  1507.                     else {
  1508.                         return TypeDescriptor.GetProperties(_type)[attr.Name];
  1509.                     }
  1510.                 }
  1511.                
  1512.                 return null;
  1513.             }
  1514.            
  1515.             /// <devdoc>
  1516.             /// Retrieves the editor for the given base type.
  1517.             /// </devdoc>
  1518.             internal object GetEditor(object instance, Type editorBaseType)
  1519.             {
  1520.                 EditorAttribute typeAttr;
  1521.                
  1522.                 // For instances, the design time object for them may want to redefine the
  1523.                 // attributes. So, we search the attribute here based on the instance. If found,
  1524.                 // we then search on the same attribute based on type. If the two don't match, then
  1525.                 // we cannot cache the value and must re-create every time. It is rare for a designer
  1526.                 // to override these attributes, so we want to be smart here.
  1527.                 //
  1528.                 if (instance != null) {
  1529.                     typeAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(_type), editorBaseType);
  1530.                     EditorAttribute instanceAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(instance), editorBaseType);
  1531.                     if (typeAttr != instanceAttr) {
  1532.                         Type editorType = GetTypeFromName(instanceAttr.EditorTypeName);
  1533.                         if (editorType != null && editorBaseType.IsAssignableFrom(editorType)) {
  1534.                             return ReflectTypeDescriptionProvider.CreateInstance(editorType, _type);
  1535.                         }
  1536.                     }
  1537.                 }
  1538.                
  1539.                 // If we got here, we return our type-based editor.
  1540.                 //
  1541.                 lock (this) {
  1542.                     for (int idx = 0; idx < _editorCount; idx++) {
  1543.                         if (_editorTypes[idx] == editorBaseType) {
  1544.                             return _editors[idx];
  1545.                         }
  1546.                     }
  1547.                 }
  1548.                
  1549.                 // Editor is not cached yet. Look in the attributes.
  1550.                 //
  1551.                 object editor = null;
  1552.                
  1553.                 typeAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(_type), editorBaseType);
  1554.                 if (typeAttr != null) {
  1555.                     Type editorType = GetTypeFromName(typeAttr.EditorTypeName);
  1556.                     if (editorType != null && editorBaseType.IsAssignableFrom(editorType)) {
  1557.                         editor = ReflectTypeDescriptionProvider.CreateInstance(editorType, _type);
  1558.                     }
  1559.                 }
  1560.                
  1561.                 // Editor is not in the attributes. Search intrinsic tables.
  1562.                 //
  1563.                 if (editor == null) {
  1564.                     Hashtable intrinsicEditors = ReflectTypeDescriptionProvider.GetEditorTable(editorBaseType);
  1565.                     if (intrinsicEditors != null) {
  1566.                         editor = ReflectTypeDescriptionProvider.SearchIntrinsicTable(intrinsicEditors, _type);
  1567.                     }
  1568.                    
  1569.                     // As a quick sanity check, check to see that the editor we got back is of
  1570.                     // the correct type.
  1571.                     //
  1572.                     if (editor != null && !editorBaseType.IsInstanceOfType(editor)) {
  1573.                         Debug.Fail("Editor " + editor.GetType().FullName + " is not an instance of " + editorBaseType.FullName + " but it is in that base types table.");
  1574.                         editor = null;
  1575.                     }
  1576.                 }
  1577.                
  1578.                 if (editor != null) {
  1579.                     lock (this) {
  1580.                         if (_editorTypes == null || _editorTypes.Length == _editorCount) {
  1581.                             int newLength = (_editorTypes == null ? 4 : _editorTypes.Length * 2);
  1582.                            
  1583.                             Type[] newTypes = new Type[newLength];
  1584.                             object[] newEditors = new object[newLength];
  1585.                            
  1586.                             if (_editorTypes != null) {
  1587.                                 _editorTypes.CopyTo(newTypes, 0);
  1588.                                 _editors.CopyTo(newEditors, 0);
  1589.                             }
  1590.                            
  1591.                             _editorTypes = newTypes;
  1592.                             _editors = newEditors;
  1593.                            
  1594.                             _editorTypes[_editorCount] = editorBaseType;
  1595.                             _editors[_editorCount++] = editor;
  1596.                         }
  1597.                     }
  1598.                 }
  1599.                
  1600.                 return editor;
  1601.             }
  1602.            
  1603.             /// <devdoc>
  1604.             /// Helper method to return an editor attribute of the correct base type.
  1605.             /// </devdoc>
  1606.             private static EditorAttribute GetEditorAttribute(AttributeCollection attributes, Type editorBaseType)
  1607.             {
  1608.                 foreach (Attribute attr in attributes) {
  1609.                     EditorAttribute edAttr = attr as EditorAttribute;
  1610.                     if (edAttr != null) {
  1611.                         Type attrEditorBaseType = Type.GetType(edAttr.EditorBaseTypeName);
  1612.                        
  1613.                         if (attrEditorBaseType != null && attrEditorBaseType == editorBaseType) {
  1614.                             return edAttr;
  1615.                         }
  1616.                     }
  1617.                 }
  1618.                
  1619.                 return null;
  1620.             }
  1621.            
  1622.             /// <devdoc>
  1623.             /// Retrieves the events for this type.
  1624.             /// </devdoc>
  1625.             internal EventDescriptorCollection GetEvents()
  1626.             {
  1627.                 // Worst case collision scenario: we don't want the perf hit
  1628.                 // of taking a lock, so if we collide we will query for
  1629.                 // events twice. Not a big deal.
  1630.                 //
  1631.                 if (_events == null) {
  1632.                     TypeDescriptor.Trace("Events : Building collection for {0}", _type.Name);
  1633.                    
  1634.                     EventDescriptor[] eventArray;
  1635.                     Hashtable eventHash = new Hashtable(16, BackCompatibleStringComparer.Default);
  1636.                     Type baseType = _type;
  1637.                     Type objType = typeof(object);
  1638.                    
  1639.                     do {
  1640.                         eventArray = ReflectGetEvents(baseType);
  1641.                         foreach (EventDescriptor ed in eventArray) {
  1642.                             if (!eventHash.ContainsKey(ed.Name)) {
  1643.                                 eventHash.Add(ed.Name, ed);
  1644.                             }
  1645.                         }
  1646.                         baseType = baseType.BaseType;
  1647.                     }
  1648.                     while (baseType != null && baseType != objType);
  1649.                    
  1650.                     eventArray = new EventDescriptor[eventHash.Count];
  1651.                     eventHash.Values.CopyTo(eventArray, 0);
  1652.                     _events = new EventDescriptorCollection(eventArray, true);
  1653.                 }
  1654.                
  1655.                 return _events;
  1656.             }
  1657.            
  1658.             /// <devdoc>
  1659.             /// Retrieves the properties for this type.
  1660.             /// </devdoc>
  1661.             internal PropertyDescriptorCollection GetProperties()
  1662.             {
  1663.                 // Worst case collision scenario: we don't want the perf hit
  1664.                 // of taking a lock, so if we collide we will query for
  1665.                 // properties twice. Not a big deal.
  1666.                 //
  1667.                 if (_properties == null) {
  1668.                     TypeDescriptor.Trace("Properties : Building collection for {0}", _type.Name);
  1669.                    
  1670.                     PropertyDescriptor[] propertyArray;
  1671.                     Hashtable propertyHash = new Hashtable(10, BackCompatibleStringComparer.Default);
  1672.                     Type baseType = _type;
  1673.                     Type objType = typeof(object);
  1674.                    
  1675.                     do {
  1676.                         propertyArray = ReflectGetProperties(baseType);
  1677.                         foreach (PropertyDescriptor p in propertyArray) {
  1678.                             if (!propertyHash.ContainsKey(p.Name)) {
  1679.                                 propertyHash.Add(p.Name, p);
  1680.                             }
  1681.                         }
  1682.                         baseType = baseType.BaseType;
  1683.                     }
  1684.                     while (baseType != null && baseType != objType);
  1685.                    
  1686.                     propertyArray = new PropertyDescriptor[propertyHash.Count];
  1687.                     propertyHash.Values.CopyTo(propertyArray, 0);
  1688.                     _properties = new PropertyDescriptorCollection(propertyArray, true);
  1689.                 }
  1690.                
  1691.                 return _properties;
  1692.             }
  1693.            
  1694.             /// <devdoc>
  1695.             /// Retrieves a type from a name. The Assembly of the type
  1696.             /// that this PropertyDescriptor came from is first checked,
  1697.             /// then a global Type.GetType is performed.
  1698.             /// </devdoc>
  1699.             private Type GetTypeFromName(string typeName)
  1700.             {
  1701.                
  1702.                 if (typeName == null || typeName.Length == 0) {
  1703.                     return null;
  1704.                 }
  1705.                
  1706.                 int commaIndex = typeName.IndexOf(',');
  1707.                 Type t = null;
  1708.                
  1709.                 if (commaIndex == -1) {
  1710.                     t = _type.Assembly.GetType(typeName);
  1711.                 }
  1712.                
  1713.                 if (t == null) {
  1714.                     t = Type.GetType(typeName);
  1715.                 }
  1716.                
  1717.                 if (t == null && commaIndex != -1) {
  1718.                     // At design time, it's possible for us to reuse
  1719.                     // an assembly but add new types. The app domain
  1720.                     // will cache the assembly based on identity, however,
  1721.                     // so it could be looking in the previous version
  1722.                     // of the assembly and not finding the type. We work
  1723.                     // around this by looking for the non-assembly qualified
  1724.                     // name, which causes the domain to raise a type
  1725.                     // resolve event.
  1726.                     //
  1727.                     t = Type.GetType(typeName.Substring(0, commaIndex));
  1728.                 }
  1729.                
  1730.                 return t;
  1731.             }
  1732.            
  1733.             /// <devdoc>
  1734.             /// Refreshes the contents of this type descriptor. This does not
  1735.             /// actually requery, but it will clear our state so the next
  1736.             /// query re-populates.
  1737.             /// </devdoc>
  1738.             internal void Refresh()
  1739.             {
  1740.                 _attributes = null;
  1741.                 _events = null;
  1742.                 _properties = null;
  1743.                 _converter = null;
  1744.                 _editors = null;
  1745.                 _editorTypes = null;
  1746.                 _editorCount = 0;
  1747.             }
  1748.         }
  1749.     }
  1750. }

Developer Fusion