private object SearchIntrinsicTable(Hashtable table) {
object hashEntry = null;
Type baseType = componentType;
// 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) {
// Here is where we put all special case logic for various intrinsics
// that cannot be directly mapped to a type.
//
if (componentType.IsCOMObject) {
// placeholder for COM converters, etc.
}
else {
if (componentType.IsEnum) {
hashEntry = table[intrinsicEnumKey];
}
}
// Normal path -- start traversing up the class hierarchy
// looking for matches.
//
if (hashEntry == null) {
while (baseType != null && baseType != typeof(object)) {
hashEntry = table[baseType];
// If the entry is a late-bound type, then try to
// resolve it.
//
if (hashEntry is string) {
hashEntry = Type.GetType((string)hashEntry);
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) {
foreach (object current in table.Keys) {
if (current is Type) {
Type keyType = (Type)current;
if (keyType.IsInterface && keyType.IsAssignableFrom(componentType)) {
hashEntry = table[keyType];
if (hashEntry is string) {
hashEntry = Type.GetType((string)hashEntry);
if (hashEntry != null) {
table[componentType] = hashEntry;
}
}
if (hashEntry != null) {
break;
}
}
}
}
}
// Finally, check to see if the component type is some unknown interface.
// We have a custom converter for that.
//
if (hashEntry == null && componentType.IsInterface) {
hashEntry = table[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.
//
if (hashEntry is Type) {
Type type = (Type)hashEntry;
hashEntry = CreateInstance(type);
if (type.GetConstructor(typeConstructor) == null) {
table[componentType] = hashEntry;
}
}
}
return hashEntry;
}