MegaBites-AI/Windows-powershell
0372
1// Licensed to the .NET Foundation under one or more agreements.2// The .NET Foundation licenses this file to you under the MIT license.3 4using System;5using System.Reflection;6 7namespace System.Management.Automation.ComInterop8{9 internal static class TypeUtils10 {11 //CONFORMING12 internal static Type GetNonNullableType(Type type)13 {14 if (IsNullableType(type))15 {16 return type.GetGenericArguments()[0];17 }18 return type;19 }20 21 //CONFORMING22 internal static bool IsNullableType(this Type type)23 {24 return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);25 }26 27 //CONFORMING28 internal static bool AreReferenceAssignable(Type dest, Type src)29 {30 // WARNING: This actually implements "Is this identity assignable and/or reference assignable?"31 if (dest == src)32 {33 return true;34 }35 if (!dest.IsValueType && !src.IsValueType && AreAssignable(dest, src))36 {37 return true;38 }39 return false;40 }41 42 //CONFORMING43 internal static bool AreAssignable(Type dest, Type src)44 {45 if (dest == src)46 {47 return true;48 }49 if (dest.IsAssignableFrom(src))50 {51 return true;52 }53 if (dest.IsArray && src.IsArray && dest.GetArrayRank() == src.GetArrayRank() && AreReferenceAssignable(dest.GetElementType(), src.GetElementType()))54 {55 return true;56 }57 if (src.IsArray && dest.IsGenericType &&58 (dest.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IEnumerable<>)59 || dest.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IList<>)60 || dest.GetGenericTypeDefinition() == typeof(System.Collections.Generic.ICollection<>))61 && dest.GetGenericArguments()[0] == src.GetElementType())62 {63 return true;64 }65 return false;66 }67 68 //CONFORMING69 internal static bool IsImplicitlyConvertible(Type source, Type destination)70 {71 return IsIdentityConversion(source, destination) ||72 IsImplicitNumericConversion(source, destination) ||73 IsImplicitReferenceConversion(source, destination) ||74 IsImplicitBoxingConversion(source, destination);75 }76 77 internal static bool IsImplicitlyConvertible(Type source, Type destination, bool considerUserDefined)78 {79 return IsImplicitlyConvertible(source, destination) ||80 (considerUserDefined && GetUserDefinedCoercionMethod(source, destination, true) != null);81 }82 83 //CONFORMING84 internal static MethodInfo GetUserDefinedCoercionMethod(Type convertFrom, Type convertToType, bool implicitOnly)85 {86 // check for implicit coercions first87 Type nnExprType = TypeUtils.GetNonNullableType(convertFrom);88 Type nnConvType = TypeUtils.GetNonNullableType(convertToType);89 // try exact match on types90 MethodInfo[] eMethods = nnExprType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);91 MethodInfo method = FindConversionOperator(eMethods, convertFrom, convertToType, implicitOnly);92 if (method != null)93 {94 return method;95 }96 MethodInfo[] cMethods = nnConvType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);97 method = FindConversionOperator(cMethods, convertFrom, convertToType, implicitOnly);98 if (method != null)99 {100 return method;101 }102 // try lifted conversion103 if (nnExprType != convertFrom || nnConvType != convertToType)104 {105 method =106 FindConversionOperator(eMethods, nnExprType, nnConvType, implicitOnly) ??107 FindConversionOperator(cMethods, nnExprType, nnConvType, implicitOnly);108 if (method != null)109 {110 return method;111 }112 }113 return null;114 }115 116 //CONFORMING117 internal static MethodInfo FindConversionOperator(MethodInfo[] methods, Type typeFrom, Type typeTo, bool implicitOnly)118 {119 foreach (MethodInfo mi in methods)120 {121 if (mi.Name != "op_Implicit" && (implicitOnly || mi.Name != "op_Explicit"))122 continue;123 if (mi.ReturnType != typeTo)124 continue;125 ParameterInfo[] pis = mi.GetParameters();126 if (pis[0].ParameterType != typeFrom)127 continue;128 return mi;129 }130 return null;131 }132 133 //CONFORMING134 private static bool IsIdentityConversion(Type source, Type destination)135 {136 return source == destination;137 }138 139 //CONFORMING140 private static bool IsImplicitNumericConversion(Type source, Type destination)141 {142 TypeCode tcSource = Type.GetTypeCode(source);143 TypeCode tcDest = Type.GetTypeCode(destination);144 145 switch (tcSource)146 {147 case TypeCode.SByte:148 switch (tcDest)149 {150 case TypeCode.Int16:151 case TypeCode.Int32:152 case TypeCode.Int64:153 case TypeCode.Single:154 case TypeCode.Double:155 case TypeCode.Decimal:156 return true;157 }158 return false;159 case TypeCode.Byte:160 switch (tcDest)161 {162 case TypeCode.Int16:163 case TypeCode.UInt16:164 case TypeCode.Int32:165 case TypeCode.UInt32:166 case TypeCode.Int64:167 case TypeCode.UInt64:168 case TypeCode.Single:169 case TypeCode.Double:170 case TypeCode.Decimal:171 return true;172 }173 return false;174 case TypeCode.Int16:175 switch (tcDest)176 {177 case TypeCode.Int32:178 case TypeCode.Int64:179 case TypeCode.Single:180 case TypeCode.Double:181 case TypeCode.Decimal:182 return true;183 }184 return false;185 case TypeCode.UInt16:186 switch (tcDest)187 {188 case TypeCode.Int32:189 case TypeCode.UInt32:190 case TypeCode.Int64:191 case TypeCode.UInt64:192 case TypeCode.Single:193 case TypeCode.Double:194 case TypeCode.Decimal:195 return true;196 }197 return false;198 case TypeCode.Int32:199 switch (tcDest)200 {201 case TypeCode.Int64:202 case TypeCode.Single:203 case TypeCode.Double:204 case TypeCode.Decimal:205 return true;206 }207 return false;208 case TypeCode.UInt32:209 switch (tcDest)210 {211 case TypeCode.UInt32:212 case TypeCode.UInt64:213 case TypeCode.Single:214 case TypeCode.Double:215 case TypeCode.Decimal:216 return true;217 }218 return false;219 case TypeCode.Int64:220 case TypeCode.UInt64:221 switch (tcDest)222 {223 case TypeCode.Single:224 case TypeCode.Double:225 case TypeCode.Decimal:226 return true;227 }228 return false;229 case TypeCode.Char:230 switch (tcDest)231 {232 case TypeCode.UInt16:233 case TypeCode.Int32:234 case TypeCode.UInt32:235 case TypeCode.Int64:236 case TypeCode.UInt64:237 case TypeCode.Single:238 case TypeCode.Double:239 case TypeCode.Decimal:240 return true;241 }242 return false;243 case TypeCode.Single:244 return (tcDest == TypeCode.Double);245 }246 return false;247 }248 249 //CONFORMING250 private static bool IsImplicitReferenceConversion(Type source, Type destination)251 {252 return AreAssignable(destination, source);253 }254 255 //CONFORMING256 private static bool IsImplicitBoxingConversion(Type source, Type destination)257 {258 if (source.IsValueType && (destination == typeof(object) || destination == typeof(System.ValueType)))259 return true;260 if (source.IsEnum && destination == typeof(System.Enum))261 return true;262 return false;263 }264 }265}266 