示例#1
0
            /// <summary>
            ///     Retrieves the type converter.  If instance is non-null,
            ///     it will be used to retrieve attributes.  Otherwise, _type
            ///     will be used.
            /// </summary>
            internal TypeConverter GetConverter(object instance)
            {
                TypeConverterAttribute typeAttr = null;

                // For instances, the design time object for them may want to redefine the
                // attributes.  So, we search the attribute here based on the instance.  If found,
                // we then search on the same attribute based on type.  If the two don't match, then
                // we cannot cache the value and must re-create every time.  It is rare for a designer
                // to override these attributes, so we want to be smart here.
                //
                if (instance != null)
                {
                    typeAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(_type)[typeof(TypeConverterAttribute)];
                    TypeConverterAttribute instanceAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(instance)[typeof(TypeConverterAttribute)];
                    if (typeAttr != instanceAttr)
                    {
                        Type converterType = GetTypeFromName(instanceAttr.ConverterTypeName);
                        if (converterType != null && typeof(TypeConverter).GetTypeInfo().IsAssignableFrom(converterType))
                        {
                            return((TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type));
                        }
                    }
                }

                // If we got here, we return our type-based converter.
                //
                if (_converter == null)
                {
                    if (typeAttr == null)
                    {
                        typeAttr = (TypeConverterAttribute)TypeDescriptor.GetAttributes(_type)[typeof(TypeConverterAttribute)];
                    }

                    if (typeAttr != null)
                    {
                        Type converterType = GetTypeFromName(typeAttr.ConverterTypeName);
                        if (converterType != null && typeof(TypeConverter).GetTypeInfo().IsAssignableFrom(converterType))
                        {
                            _converter = (TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type);
                        }
                    }

                    if (_converter == null)
                    {
                        // We did not get a converter.  Traverse up the base class chain until
                        // we find one in the stock hashtable.
                        //
                        _converter = (TypeConverter)ReflectTypeDescriptionProvider.SearchIntrinsicTable(IntrinsicTypeConverters, _type);
                        Debug.Assert(_converter != null, "There is no intrinsic setup in the hashtable for the Object type");
                    }
                }

                return(_converter);
            }
示例#2
0
            /// <summary>
            ///     Retrieves the editor for the given base type.
            /// </summary>
            internal object GetEditor(object instance, Type editorBaseType)
            {
                EditorAttribute typeAttr;

                // For instances, the design time object for them may want to redefine the
                // attributes.  So, we search the attribute here based on the instance.  If found,
                // we then search on the same attribute based on type.  If the two don't match, then
                // we cannot cache the value and must re-create every time.  It is rare for a designer
                // to override these attributes, so we want to be smart here.
                //
                if (instance != null)
                {
                    typeAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(_type), editorBaseType);
                    EditorAttribute instanceAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(instance), editorBaseType);
                    if (typeAttr != instanceAttr)
                    {
                        Type editorType = GetTypeFromName(instanceAttr.EditorTypeName);
                        if (editorType != null && editorBaseType.GetTypeInfo().IsAssignableFrom(editorType))
                        {
                            return(ReflectTypeDescriptionProvider.CreateInstance(editorType, _type));
                        }
                    }
                }

                // If we got here, we return our type-based editor.
                //
                lock (this)
                {
                    for (int idx = 0; idx < _editorCount; idx++)
                    {
                        if (_editorTypes[idx] == editorBaseType)
                        {
                            return(_editors[idx]);
                        }
                    }
                }

                // Editor is not cached yet.  Look in the attributes.
                //
                object editor = null;

                typeAttr = GetEditorAttribute(TypeDescriptor.GetAttributes(_type), editorBaseType);
                if (typeAttr != null)
                {
                    Type editorType = GetTypeFromName(typeAttr.EditorTypeName);
                    if (editorType != null && editorBaseType.GetTypeInfo().IsAssignableFrom(editorType))
                    {
                        editor = ReflectTypeDescriptionProvider.CreateInstance(editorType, _type);
                    }
                }

                // Editor is not in the attributes.  Search intrinsic tables.
                //
                if (editor == null)
                {
                    Hashtable intrinsicEditors = ReflectTypeDescriptionProvider.GetEditorTable(editorBaseType);
                    if (intrinsicEditors != null)
                    {
                        editor = ReflectTypeDescriptionProvider.SearchIntrinsicTable(intrinsicEditors, _type);
                    }

                    // As a quick sanity check, check to see that the editor we got back is of
                    // the correct type.
                    //
                    if (editor != null && !editorBaseType.GetTypeInfo().IsInstanceOfType(editor))
                    {
                        Debug.Fail($"Editor {editor.GetType().FullName} is not an instance of {editorBaseType.FullName} but it is in that base types table.");
                        editor = null;
                    }
                }

                if (editor != null)
                {
                    lock (this)
                    {
                        if (_editorTypes == null || _editorTypes.Length == _editorCount)
                        {
                            int newLength = (_editorTypes == null ? 4 : _editorTypes.Length * 2);

                            Type[]   newTypes   = new Type[newLength];
                            object[] newEditors = new object[newLength];

                            if (_editorTypes != null)
                            {
                                _editorTypes.CopyTo(newTypes, 0);
                                _editors.CopyTo(newEditors, 0);
                            }

                            _editorTypes = newTypes;
                            _editors     = newEditors;

                            _editorTypes[_editorCount] = editorBaseType;
                            _editors[_editorCount++]   = editor;
                        }
                    }
                }

                return(editor);
            }
        /// <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);
        }
        /// <devdoc>
        ///    Gets a type converter for the specified type.
        /// </devdoc>
        internal static TypeConverter GetConverter(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            // Obtaining attributes follows a very critical order: we must take care that
            // we merge attributes the right way.  Consider this:
            //
            // [A4]
            // interface IBase;
            //
            // [A3]
            // interface IDerived;
            //
            // [A2]
            // class Base : IBase;
            //
            // [A1]
            // class Derived : Base, IDerived
            //
            // We are retreving attributes in the following order:  A1 - A4.
            // Interfaces always lose to types, and interfaces and types
            // must be looked up in the same order.
            TypeConverterAttribute converterAttribute = ReflectTypeDescriptionProvider.GetTypeConverterAttributeIfAny(type);

            if (converterAttribute == null)
            {
                Type baseType = type.GetTypeInfo().BaseType;

                while (baseType != null && baseType != typeof(object))
                {
                    converterAttribute = ReflectTypeDescriptionProvider.GetTypeConverterAttributeIfAny(baseType);
                    if (converterAttribute != null)
                    {
                        break;
                    }
                    baseType = baseType.GetTypeInfo().BaseType;
                }
            }

            if (converterAttribute == null)
            {
                IEnumerable <Type> interfaces = type.GetTypeInfo().ImplementedInterfaces;
                foreach (Type iface in interfaces)
                {
                    // only do this for public interfaces.
                    //
                    if ((iface.GetTypeInfo().Attributes & (TypeAttributes.Public | TypeAttributes.NestedPublic)) != 0)
                    {
                        converterAttribute = GetTypeConverterAttributeIfAny(iface);
                        if (converterAttribute != null)
                        {
                            break;
                        }
                    }
                }
            }

            if (converterAttribute != null)
            {
                Type converterType = ReflectTypeDescriptionProvider.GetTypeFromName(converterAttribute.ConverterTypeName, type);
                if (converterType != null && typeof(TypeConverter).GetTypeInfo().IsAssignableFrom(converterType.GetTypeInfo()))
                {
                    bool noTypeConstructor = true;
                    return((TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, type, ref noTypeConstructor));
                }
            }

            // We did not get a converter. Traverse up the base class chain until
            // we find one in the stock hashtable.
            //
            return((TypeConverter)ReflectTypeDescriptionProvider.SearchIntrinsicTable(type));
        }