Example #1
0
        //
        // 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));
        }
Example #2
0
            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);
                }
            }
Example #3
0
        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));
        }
Example #4
0
        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));
            }
        }
Example #5
0
        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);
        }
Example #6
0
        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);
            }
        }
Example #7
0
        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);
            }
        }
Example #8
0
 public static bool AreTypesAssignable(RuntimeTypeHandle sourceType, RuntimeTypeHandle targetType)
 {
     return(RuntimeImports.AreTypesAssignable(sourceType.ToEETypePtr(), targetType.ToEETypePtr()));
 }
Example #9
0
        public static bool IsAssignable(object srcObject, RuntimeTypeHandle dstType)
        {
            EETypePtr srcEEType = srcObject.EETypePtr;

            return(RuntimeImports.AreTypesAssignable(srcEEType, dstType.ToEETypePtr()));
        }
Example #10
0
        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);
            }
        }