-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
There's no test coverage for the ReflectTypeDescriptionProvider.GetIntrinsicTypeEditor method which does core work when TypeDescriptor.GetEditor and related methods are called:
Lines 1268 to 1382 in 2b93f83
| private static object GetIntrinsicTypeEditor(Hashtable table, 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 (table) | |
| { | |
| Type baseType = callingType; | |
| while (baseType != null && baseType != typeof(object)) | |
| { | |
| hashEntry = table[baseType]; | |
| // If the entry is a late-bound type, then try to | |
| // resolve it. | |
| // | |
| string typeString = hashEntry as string; | |
| if (typeString != null) | |
| { | |
| hashEntry = Type.GetType(typeString); | |
| if (hashEntry != null) | |
| { | |
| table[baseType] = hashEntry; | |
| } | |
| } | |
| if (hashEntry != null) | |
| { | |
| break; | |
| } | |
| baseType = baseType.BaseType; | |
| } | |
| // 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) | |
| { | |
| // Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations. | |
| IDictionaryEnumerator e = table.GetEnumerator(); | |
| while (e.MoveNext()) | |
| { | |
| DictionaryEntry de = e.Entry; | |
| Type keyType = de.Key as Type; | |
| if (keyType != null && keyType.IsInterface && keyType.IsAssignableFrom(callingType)) | |
| { | |
| hashEntry = de.Value; | |
| string typeString = hashEntry as string; | |
| if (typeString != null) | |
| { | |
| hashEntry = Type.GetType(typeString); | |
| if (hashEntry != null) | |
| { | |
| table[callingType] = hashEntry; | |
| } | |
| } | |
| if (hashEntry != null) | |
| { | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| // Special case converters | |
| // | |
| if (hashEntry == null) | |
| { | |
| if (callingType.IsGenericType && callingType.GetGenericTypeDefinition() == typeof(Nullable<>)) | |
| { | |
| // Check if it is a nullable value | |
| hashEntry = table[s_intrinsicNullableKey]; | |
| } | |
| else if (callingType.IsInterface) | |
| { | |
| // Finally, check to see if the component type is some unknown interface. | |
| // We have a custom converter for that. | |
| hashEntry = table[s_intrinsicReferenceKey]; | |
| } | |
| } | |
| // Interfaces do not derive from object, so we | |
| // must handle the case of no hash entry here. | |
| // | |
| if (hashEntry == null) | |
| { | |
| hashEntry = table[typeof(object)]; | |
| } | |
| // 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) | |
| { | |
| hashEntry = CreateInstance(type, callingType); | |
| if (type.GetConstructor(s_typeConstructor) == null) | |
| { | |
| table[callingType] = hashEntry; | |
| } | |
| } | |
| } | |
| return hashEntry; | |
| } |
The method previously handled look ups for both type converters and editors, but #39973 split the logic into separate methods to facilitate linker friendliness of intrinsic type converters. As a result, the following block of code (specific to converter look-ups ) can probably be removed from GetIntrinsicTypeEditor:
Lines 1339 to 1354 in 2b93f83
| // Special case converters | |
| // | |
| if (hashEntry == null) | |
| { | |
| if (callingType.IsGenericType && callingType.GetGenericTypeDefinition() == typeof(Nullable<>)) | |
| { | |
| // Check if it is a nullable value | |
| hashEntry = table[s_intrinsicNullableKey]; | |
| } | |
| else if (callingType.IsInterface) | |
| { | |
| // Finally, check to see if the component type is some unknown interface. | |
| // We have a custom converter for that. | |
| hashEntry = table[s_intrinsicReferenceKey]; | |
| } | |
| } |
The PR (#39973) held off from removing this code due to a lack of test coverage for the method and to avoid breaking upstream scenarios, such as Win Forms code.
We should also investigate code coverage for other areas in the ReflectTypeDescriptionProvider class.
cc @eerhardt