Beispiel #1
0
        /// <devdoc>
        ///      Searches the provided intrinsic hashtable for a match with the object type.
        ///      At the beginning, the hashtable contains types for the various converters.
        ///      As this table is searched, the types for these objects
        ///      are replaced with instances, so we only create as needed.  This method
        ///      does the search up the base class hierarchy and will create instances
        ///      for types as needed.  These instances are stored back into the table
        ///      for the base type, and for the original component type, for fast access.
        /// </devdoc>
        private static object SearchIntrinsicTable(Type callingType)
        {
            object hashEntry = null;

            // We take a lock on this table.  Nothing in this code calls out to
            // other methods that lock, so it should be fairly safe to grab this
            // lock.  Also, this allows multiple intrinsic tables to be searched
            // at once.
            //
            lock (ReflectTypeDescriptionProvider.s_syncObject)
            {
                Type baseType = callingType;
                while (baseType != null && baseType != typeof(object))
                {
                    if (ReflectTypeDescriptionProvider.IntrinsicTypeConverters.TryGetValue(baseType, out hashEntry) && hashEntry != null)
                    {
                        break;
                    }

                    baseType = baseType.GetTypeInfo().BaseType;
                }

                TypeInfo callingTypeInfo = callingType.GetTypeInfo();

                // Now make a scan through each value in the table, looking for interfaces.
                // If we find one, see if the object implements the interface.
                //
                if (hashEntry == null)
                {
                    foreach (object key in ReflectTypeDescriptionProvider.IntrinsicTypeConverters.Keys)
                    {
                        Type keyType = key as Type;

                        if (keyType != null)
                        {
                            TypeInfo keyTypeInfo = keyType.GetTypeInfo();
                            if (keyTypeInfo.IsInterface && keyTypeInfo.IsAssignableFrom(callingTypeInfo))
                            {
                                ReflectTypeDescriptionProvider.IntrinsicTypeConverters.TryGetValue(key, out hashEntry);
                                string converterTypeString = hashEntry as string;

                                if (converterTypeString != null)
                                {
                                    hashEntry = Type.GetType(converterTypeString);
                                    if (hashEntry != null)
                                    {
                                        ReflectTypeDescriptionProvider.IntrinsicTypeConverters[callingType] = hashEntry;
                                    }
                                }

                                if (hashEntry != null)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }

                // Special case converter
                //
                if (hashEntry == null)
                {
                    if (callingTypeInfo.IsGenericType && callingTypeInfo.GetGenericTypeDefinition() == typeof(Nullable <>))
                    {
                        // Check if it is a nullable value
                        ReflectTypeDescriptionProvider.IntrinsicTypeConverters.TryGetValue(ReflectTypeDescriptionProvider.s_intrinsicNullableKey, out hashEntry);
                    }
                }

                // Interfaces do not derive from object, so we
                // must handle the case of no hash entry here.
                //
                if (hashEntry == null)
                {
                    ReflectTypeDescriptionProvider.IntrinsicTypeConverters.TryGetValue(typeof(object), out hashEntry);
                }

                // If the entry is a type, create an instance of it and then
                // replace the entry.  This way we only need to create once.
                // We can only do this if the object doesn't want a type
                // in its constructor.
                //
                Type type = hashEntry as Type;

                if (type != null)
                {
                    bool noTypeConstructor = true;
                    hashEntry = ReflectTypeDescriptionProvider.CreateInstance(type, callingType, ref noTypeConstructor);
                    if (noTypeConstructor)
                    {
                        ReflectTypeDescriptionProvider.IntrinsicTypeConverters[callingType] = hashEntry;
                    }
                }
            }
            return(hashEntry);
        }