/// <summary> /// 对指定类型执行基本的类型转换判断,包括转换为 object 和 null 转换。 /// 基本类型转换失败时,保证 value != null,nonNullableType != null。 /// </summary> /// <param name="value">要转换的对象。</param> /// <param name="conversionType">要返回的对象的类型。</param> /// <param name="nonNullableType"><paramref name="value"/> 对应的 non-nullable-type。</param> /// <returns>如果基本类型转换成功,则为 <c>true</c>;否则为 <c>false</c>。</returns> private static bool BasicChangeType(ref object value, Type conversionType, out Type nonNullableType) { CommonExceptions.CheckArgumentNull(conversionType, "conversionType"); if (conversionType.IsByRef) { conversionType = conversionType.GetElementType(); } // 总是可以转换为 Object。 if (conversionType == typeof(object)) { nonNullableType = null; return true; } // value 为 null 的情况。 bool nullableCType = TypeExt.IsNullableType(conversionType, out nonNullableType); if (value == null) { if (conversionType.IsValueType && !nullableCType) { throw CommonExceptions.CannotCastNullToValueType(); } return true; } return false; }
/// <summary> /// 找到委托的参数列表,最后一个参数总是表示返回类型。 /// </summary> /// <param name="paramTypes">处理器参数类型列表。</param> /// <param name="instanceType">实例的类型,如果不需要传入实例则为 <c>null</c>。</param> /// <returns>委托的参数列表。</returns> private static Type[] FindDelegateType(List <Type[]> paramTypes, Type instanceType) { Contract.Requires(paramTypes != null && paramTypes.Count > 0); int len = paramTypes[0].Length; Type[] types; if (instanceType == null) { types = new Type[len]; } else { len++; types = new Type[len]; types[0] = instanceType; } int paramsIdx = paramTypes[0].Length - 1, typesIdx = len - 1; Contract.Assume(paramsIdx >= 0); int returnIdx = paramsIdx; types[typesIdx] = TypeExt.GetEncompassedType(paramTypes.Select(t => t[returnIdx])) ?? typeof(object); for (; paramsIdx >= 0; paramsIdx--, typesIdx--) { int idx = paramsIdx; types[typesIdx] = TypeExt.GetEncompassingType(paramTypes.Select(t => t[idx])) ?? typeof(object); } return(types); }
/// <summary> /// 返回从源类型到目标类型的用户定义的隐式转换方法。 /// 该转换方法的参数与源类型和目标类型并不一定完全相同,但保证存在标准隐式转换。 /// 不支持提升转换运算符,不允许两个类同时为 nullable 类型。 /// </summary> /// <param name="sourceType">要获取用户定义的转换方法的源类型。</param> /// <param name="targetType">要获取用户定义的转换方法的目标类型。</param> /// <returns>如果存在从源类型到目标类型的用户定义的隐式转换方法,则返回该方法; /// 否则返回 <c>null</c>。</returns> public static ConversionMethod GetImplicitConversion(Type sourceType, Type targetType) { Debug.Assert(!(sourceType.IsNullableType() && targetType.IsNullableType())); Type exactSource = null, exactTarget = null; UniqueValue <ConversionMethod> method = new UniqueValue <ConversionMethod>(); Conversion conv = GetTypeConversions(TypeExt.GetNonNullableType(targetType)); for (int i = conv.ImplicitConvertFromIndex; i < conv.ConvertToIndex; i++) { ConversionMethod m = conv.Methods[i]; if (m.SourceType.IsStandardImplicitFrom(sourceType)) { GetBestConversion(m, ref exactSource, ref exactTarget, method); } } if (!sourceType.IsNullableType()) { conv = GetTypeConversions(sourceType); for (int i = conv.ImplicitConvertToIndex; i < conv.Methods.Length; i++) { ConversionMethod m = conv.Methods[i]; if (targetType.IsStandardImplicitFrom(m.TargetType)) { GetBestConversion(m, ref exactSource, ref exactTarget, method); } } } if (method.IsUnique) { return(method.Value); } return(null); }
/// <summary> /// 根据给定的类型数组推断泛型方法的类型参数。 /// </summary> /// <param name="method">要推断类型参数的泛型方法。</param> /// <param name="parameters">泛型方法的形参参数数组。</param> /// <param name="types">实参参数数组。</param> /// <returns>如果成功推断泛型方法的类型参数,则为类型参数数组; /// 如果推断失败或给定的方法不是泛型方法定义,则为 <c>null</c>。</returns> internal static Type[] GenericArgumentsInferences(this MethodBase method, ParameterInfo[] parameters, Type[] types) { Debug.Assert(method.IsGenericMethodDefinition); Debug.Assert(parameters != null); Debug.Assert(types != null); int len = parameters.Length > types.Length ? parameters.Length : types.Length; int[] paramOrder = GetParamOrder(len); Type paramArrayType; if (CheckParameterCount(parameters, types, paramOrder, true, out paramArrayType)) { Type[] paramTypes = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { paramTypes[i] = parameters[i].ParameterType; } return(TypeExt.GenericArgumentsInferences(method.GetGenericArguments(), paramTypes, ref paramArrayType, types, paramOrder)); } return(null); }
/// <summary> /// 使用类型数组的元素替代泛型方法定义的类型参数,并返回是否成功的标志。 /// </summary> /// <param name="match">泛型方法的信息。</param> /// <param name="types">要替换泛型方法定义的类型参数的类型数组。</param> /// <returns>如果构造封闭的泛型方法,或者不是泛型方法则为 <c>true</c>; /// 如果没能成功构造封闭的泛型方法,则为 <c>false</c>。</returns> private static bool MakeGenericMethod(MatchInfo match, Type[] types) { MethodInfo method = match.Method as MethodInfo; if (method == null || !match.IsGeneric) { return(true); } Type[] paramTypes = new Type[match.Parameters.Length]; for (int i = 0; i < match.Parameters.Length; i++) { paramTypes[i] = match.Parameters[i].ParameterType; } Type paramArrayType = match.ParamArrayType; Type[] args = TypeExt.GenericArgumentsInferences(method.GetGenericArguments(), paramTypes, ref paramArrayType, types, match.ParamOrder); match.ParamArrayType = paramArrayType; try { method = method.MakeGenericMethod(args); } catch (ArgumentException) { // 不满足方法的约束。 return(false); } // 更新方法信息。 match.Method = method; match.Parameters = method.GetParameters(); match.GenericArgumentCount = args.Length; if (match.ParamArrayType != null) { match.ParamArrayType = MethodExt.GetParamArrayType(match.Parameters[match.Parameters.Length - 1]); } return(true); }