// // This implements the "IsAssignableFrom()" api for runtime-created types. By policy, we let the underlying runtime decide assignability. // public static bool IsAssignableFrom(RuntimeTypeHandle dstType, RuntimeTypeHandle srcType) { EETypePtr dstEEType = dstType.ToEETypePtr(); EETypePtr srcEEType = srcType.ToEETypePtr(); return(RuntimeImports.AreTypesAssignable(srcEEType, dstEEType)); }
protected sealed override RuntimeType Factory(EETypePtr eeType) { RuntimeImports.RhEETypeClassification classification = RuntimeImports.RhGetEETypeClassification(eeType); switch (classification) { case RuntimeImports.RhEETypeClassification.Regular: return(new RuntimeEENamedNonGenericType(eeType)); case RuntimeImports.RhEETypeClassification.Array: return(new RuntimeEEArrayType(eeType)); case RuntimeImports.RhEETypeClassification.UnmanagedPointer: return(new RuntimeEEPointerType(eeType)); case RuntimeImports.RhEETypeClassification.GenericTypeDefinition: return(new RuntimeEENamedGenericType(eeType)); case RuntimeImports.RhEETypeClassification.Generic: // Reflection blocked constructed generic types simply pretend to not be generic // This is reasonable, as the behavior of reflection blocked types is supposed // to be that they expose the minimal information about a type that is necessary // for users of Object.GetType to move from that type to a type that isn't // reflection blocked. By not revealing that reflection blocked types are generic // we are making it appear as if implementation detail types exposed to user code // are all non-generic, which is theoretically possible, and by doing so // we avoid (in all known circumstances) the very complicated case of representing // the interfaces, base types, and generic parameter types of reflection blocked // generic type definitions. if (RuntimeAugments.Callbacks.IsReflectionBlocked(new RuntimeTypeHandle(eeType))) { return(new RuntimeEENamedNonGenericType(eeType)); } if (RuntimeImports.AreTypesAssignable(eeType, typeof(MDArrayRank2).TypeHandle.ToEETypePtr())) { return(new RuntimeEEArrayType(eeType, rank: 2)); } if (RuntimeImports.AreTypesAssignable(eeType, typeof(MDArrayRank3).TypeHandle.ToEETypePtr())) { return(new RuntimeEEArrayType(eeType, rank: 3)); } if (RuntimeImports.AreTypesAssignable(eeType, typeof(MDArrayRank4).TypeHandle.ToEETypePtr())) { return(new RuntimeEEArrayType(eeType, rank: 4)); } return(new RuntimeEEConstructedGenericType(eeType)); default: throw new ArgumentException(SR.Arg_InvalidRuntimeTypeHandle); } }
private static Exception ConvertPointerIfPossible(object srcObject, EETypePtr srcEEType, EETypePtr dstEEType, CheckArgumentSemantics semantics, out IntPtr dstIntPtr) { if (srcObject is IntPtr srcIntPtr) { dstIntPtr = srcIntPtr; return(null); } if (srcObject is Pointer srcPointer) { if (dstEEType == typeof(void *).TypeHandle.ToEETypePtr() || RuntimeImports.AreTypesAssignable(pSourceType: srcPointer.GetPointerType().TypeHandle.ToEETypePtr(), pTargetType: dstEEType)) { dstIntPtr = srcPointer.GetPointerValue(); return(null); } } dstIntPtr = IntPtr.Zero; return(CreateChangeTypeException(srcEEType, dstEEType, semantics)); }
internal static object?CheckArgument(object?srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle?binderBundle) { // Methods with ByRefLike types in signatures should be filtered out earlier Debug.Assert(!dstEEType.IsByRefLike); if (srcObject == null) { // null -> default(T) if (dstEEType.IsPointer) { return(default(IntPtr)); } else if (dstEEType.IsValueType && !dstEEType.IsNullable) { if (semantics == CheckArgumentSemantics.SetFieldDirect) { throw CreateChangeTypeException(typeof(object).TypeHandle.ToEETypePtr(), dstEEType, semantics); } return(Runtime.RuntimeImports.RhNewObject(dstEEType)); } else { return(null); } } else { EETypePtr srcEEType = srcObject.GetEETypePtr(); if (srcEEType.RawValue == dstEEType.RawValue || RuntimeImports.AreTypesAssignable(srcEEType, dstEEType) || (dstEEType.IsInterface && srcObject is Runtime.InteropServices.IDynamicInterfaceCastable castable && castable.IsInterfaceImplemented(new RuntimeTypeHandle(dstEEType), throwIfNotImplemented: false))) { return(srcObject); } return(CheckArgumentConversions(srcObject, dstEEType, semantics, binderBundle)); } }
private static bool ImplementsIComparable(RuntimeTypeHandle t) { EETypePtr objectType = t.ToEETypePtr(); EETypePtr icomparableType = typeof(IComparable <>).TypeHandle.ToEETypePtr(); int interfaceCount = objectType.Interfaces.Count; for (int i = 0; i < interfaceCount; i++) { EETypePtr interfaceType = objectType.Interfaces[i]; if (!interfaceType.IsGeneric) { continue; } if (interfaceType.GenericDefinition == icomparableType) { var instantiation = interfaceType.Instantiation; if (instantiation.Length != 1) { continue; } if (objectType.IsValueType) { if (instantiation[0] == objectType) { return(true); } } else if (RuntimeImports.AreTypesAssignable(objectType, instantiation[0])) { return(true); } } } return(false); }
internal static Object CheckArgument(Object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle binderBundle, Func <Type> getExactTypeForCustomBinder = null) { if (srcObject == null) { // null -> default(T) if (dstEEType.IsValueType && !dstEEType.IsNullable) { if (semantics == CheckArgumentSemantics.SetFieldDirect) { throw CreateChangeTypeException(CommonRuntimeTypes.Object.TypeHandle.ToEETypePtr(), dstEEType, semantics); } return(Runtime.RuntimeImports.RhNewObject(dstEEType)); } else { return(null); } } else { EETypePtr srcEEType = srcObject.EETypePtr; if (RuntimeImports.AreTypesAssignable(srcEEType, dstEEType)) { return(srcObject); } if (dstEEType.IsInterface) { ICastable castable = srcObject as ICastable; Exception castError; if (castable != null && castable.IsInstanceOfInterface(new RuntimeTypeHandle(dstEEType), out castError)) { return(srcObject); } } object dstObject; Exception exception = ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(srcObject, srcEEType, dstEEType, semantics, out dstObject); if (exception == null) { return(dstObject); } if (binderBundle == null) { throw exception; } // Our normal coercion rules could not convert the passed in argument but we were supplied a custom binder. See if it can do it. Type exactDstType; if (getExactTypeForCustomBinder == null) { // We were called by someone other than DynamicInvokeParamHelperCore(). Those callers pass the correct dstEEType. exactDstType = Type.GetTypeFromHandle(new RuntimeTypeHandle(dstEEType)); } else { // We were called by DynamicInvokeParamHelperCore(). He passes a dstEEType that enums folded to int and possibly other adjustments. A custom binder // is app code however and needs the exact type. exactDstType = getExactTypeForCustomBinder(); } srcObject = binderBundle.ChangeType(srcObject, exactDstType); // For compat with desktop, the result of the binder call gets processed through the default rules again. dstObject = CheckArgument(srcObject, dstEEType, semantics, binderBundle: null, getExactTypeForCustomBinder: null); return(dstObject); } }
internal static object?CheckArgument(object?srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle?binderBundle, ref ArgSetupState argSetupState) { // Methods with ByRefLike types in signatures should be filtered out by the compiler Debug.Assert(!dstEEType.IsByRefLike); if (srcObject == null) { // null -> default(T) if (dstEEType.IsPointer) { return(default(IntPtr)); } else if (dstEEType.IsValueType && !dstEEType.IsNullable) { if (semantics == CheckArgumentSemantics.SetFieldDirect) { throw CreateChangeTypeException(typeof(object).TypeHandle.ToEETypePtr(), dstEEType, semantics); } return(Runtime.RuntimeImports.RhNewObject(dstEEType)); } else { return(null); } } else { EETypePtr srcEEType = srcObject.EETypePtr; if (RuntimeImports.AreTypesAssignable(srcEEType, dstEEType)) { return(srcObject); } if (dstEEType.IsInterface) { if (srcObject is Runtime.InteropServices.IDynamicInterfaceCastable castable && castable.IsInterfaceImplemented(new RuntimeTypeHandle(dstEEType), throwIfNotImplemented: false)) { return(srcObject); } } object dstObject; Exception exception = ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(srcObject, srcEEType, dstEEType, semantics, out dstObject); if (exception == null) { return(dstObject); } if (binderBundle == null) { throw exception; } // Our normal coercion rules could not convert the passed in argument but we were supplied a custom binder. See if it can do it. Type exactDstType; if (Unsafe.IsNullRef(ref argSetupState)) { // We were called by someone other than DynamicInvokeParamHelperCore(). Those callers pass the correct dstEEType. exactDstType = Type.GetTypeFromHandle(new RuntimeTypeHandle(dstEEType)) !; } else { // We were called by DynamicInvokeParamHelperCore(). He passes a dstEEType that enums folded to int and possibly other adjustments. A custom binder // is app code however and needs the exact type. exactDstType = GetExactTypeForCustomBinder(argSetupState); } srcObject = binderBundle.ChangeType(srcObject, exactDstType); // For compat with desktop, the result of the binder call gets processed through the default rules again. dstObject = CheckArgument(srcObject, dstEEType, semantics, binderBundle: null, ref Unsafe.NullRef <ArgSetupState>()); return(dstObject); } }
public static bool AreTypesAssignable(RuntimeTypeHandle sourceType, RuntimeTypeHandle targetType) { return(RuntimeImports.AreTypesAssignable(sourceType.ToEETypePtr(), targetType.ToEETypePtr())); }
public static bool IsAssignable(object srcObject, RuntimeTypeHandle dstType) { EETypePtr srcEEType = srcObject.EETypePtr; return(RuntimeImports.AreTypesAssignable(srcEEType, dstType.ToEETypePtr())); }
internal static Object CheckArgument(Object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics) { if (srcObject == null) { // null -> default(T) if (dstEEType.IsValueType && !dstEEType.IsNullable) { return(Runtime.RuntimeImports.RhNewObject(dstEEType)); } else { return(null); } } else { EETypePtr srcEEType = srcObject.EETypePtr; if (RuntimeImports.AreTypesAssignable(srcEEType, dstEEType)) { return(srcObject); } if (dstEEType.IsInterface) { ICastable castable = srcObject as ICastable; Exception castError; if (castable != null && castable.IsInstanceOfInterface(new RuntimeTypeHandle(dstEEType), out castError)) { return(srcObject); } } if (!((srcEEType.IsEnum || srcEEType.IsPrimitive) && (dstEEType.IsEnum || dstEEType.IsPrimitive))) { throw CreateChangeTypeException(srcEEType, dstEEType, semantics); } RuntimeImports.RhCorElementType dstCorElementType = dstEEType.CorElementType; if (!srcEEType.CorElementTypeInfo.CanWidenTo(dstCorElementType)) { throw CreateChangeTypeArgumentException(srcEEType, dstEEType); } Object dstObject; switch (dstCorElementType) { case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN: dstObject = Convert.ToBoolean(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR: dstObject = Convert.ToChar(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1: dstObject = Convert.ToSByte(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2: dstObject = Convert.ToInt16(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4: dstObject = Convert.ToInt32(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8: dstObject = Convert.ToInt64(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1: dstObject = Convert.ToByte(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2: dstObject = Convert.ToUInt16(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4: dstObject = Convert.ToUInt32(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8: dstObject = Convert.ToUInt64(srcObject); break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R4: if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR) { dstObject = (float)(char)srcObject; } else { dstObject = Convert.ToSingle(srcObject); } break; case RuntimeImports.RhCorElementType.ELEMENT_TYPE_R8: if (srcEEType.CorElementType == RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR) { dstObject = (double)(char)srcObject; } else { dstObject = Convert.ToDouble(srcObject); } break; default: Debug.Assert(false, "Unexpected CorElementType: " + dstCorElementType + ": Not a valid widening target."); throw CreateChangeTypeException(srcEEType, dstEEType, semantics); } if (dstEEType.IsEnum) { Type dstType = ReflectionCoreNonPortable.GetRuntimeTypeForEEType(dstEEType); dstObject = Enum.ToObject(dstType, dstObject); } Debug.Assert(dstObject.EETypePtr == dstEEType); return(dstObject); } }