public sealed override bool IsAssignableFrom(TypeInfo typeInfo) { RuntimeTypeInfo toTypeInfo = this; if (typeInfo == null || !typeInfo.IsRuntimeImplemented()) return false; // Desktop compat: If typeInfo is null, or implemented by a different Reflection implementation, return "false." RuntimeTypeInfo fromTypeInfo = typeInfo.CastToRuntimeTypeInfo(); if (toTypeInfo.Equals(fromTypeInfo)) return true; RuntimeTypeHandle toTypeHandle = toTypeInfo.InternalTypeHandleIfAvailable; RuntimeTypeHandle fromTypeHandle = fromTypeInfo.InternalTypeHandleIfAvailable; bool haveTypeHandles = !(toTypeHandle.IsNull() || fromTypeHandle.IsNull()); if (haveTypeHandles) { // If both types have type handles, let MRT handle this. It's not dependent on metadata. if (ReflectionCoreExecution.ExecutionEnvironment.IsAssignableFrom(toTypeHandle, fromTypeHandle)) return true; // Runtime IsAssignableFrom does not handle casts from generic type definitions: always returns false. For those, we fall through to the // managed implementation. For everyone else, return "false". // // Runtime IsAssignableFrom does not handle pointer -> UIntPtr cast. if (!(fromTypeInfo.IsGenericTypeDefinition || fromTypeInfo.IsPointer)) return false; } // If we got here, the types are open, or reduced away, or otherwise lacking in type handles. Perform the IsAssignability check in managed code. return Assignability.IsAssignableFrom(this, typeInfo, ReflectionCoreExecution.ExecutionDomain.FoundationTypes); }