/// <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); }
/// <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)); }