/// <summary> /// 固定当前界限集所限定的类型参数。 /// </summary> /// <returns>如果成功固定当前界限集的的类型参数,则为类型参数; /// 如果固定失败,则为 <c>null</c>。</returns> public Type FixTypeArg() { Type result; if (exactBound == null) { var types = new HashSet <Type>(lowerBounds); types.UnionWith(upperBounds); types.RemoveWhere(type => !CanFixed(type)); if (types.Count == 0) { // 没有找到合适的推断结果。 return(null); } if (types.Count == 1) { // 找到唯一的推断结果。 result = types.First(); } else { // 进一步进行推断。 result = TypeExt.GetEncompassingType(types); if (result == null) { return(null); } } } else { result = exactBound; } // 判断引用类型约束。 if (ReferenceType && result.IsValueType) { return(null); } return(result); }
/// <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); }
/// <summary> /// 寻找与 <paramref name="type"/> 匹配的最好的类型。调用保证 <paramref name="type"/> /// 可以转换为 <paramref name="firstType"/> 和 <paramref name="secondType"/>。 /// </summary> /// <param name="firstType">要比较匹配的第一个类型。</param> /// <param name="secondType">要比较匹配的第二个类型。</param> /// <param name="type">要进行匹配的类型。</param> /// <returns>如果 <paramref name="firstType"/> 与 <paramref name="type"/> 匹配的更好,则为 <c>-1</c>; /// 如果 <paramref name="secondType"/> 与 <paramref name="type"/> 匹配的更好,则为 <c>1</c>; /// 如果匹配程度相同,则为 <c>0</c>。</returns> /// <remarks>《CSharp Language Specification》 7.5.3.3 Better conversion from expression。</remarks> private int CompareType(Type firstType, Type secondType, Type type) { Contract.Requires(firstType != null && secondType != null && type != null); Contract.Ensures(Contract.Result <int>() >= -1 && Contract.Result <int>() <= 1); if (firstType == secondType) { return(0); } if (firstType == type) { return(-1); } if (secondType == type) { return(1); } bool typeByRef = type.IsByRef; // 根据 type 是否按引用传递,选择普通参数或按引用传递的参数。 if (firstType.IsByRef) { firstType = firstType.GetElementType(); if (secondType.IsByRef) { secondType = secondType.GetElementType(); } else if (firstType == secondType) { return(typeByRef ? -1 : 1); } } else if (secondType.IsByRef) { secondType = secondType.GetElementType(); if (firstType == secondType) { return(typeByRef ? 1 : -1); } } if (typeByRef) { type = type.GetElementType(); } bool firstImplicitFromType = true; if (isExplicit) { // 可以从 type 隐式转换的类型会更匹配,仅当允许显式类型转换时才需要检测。 firstImplicitFromType = firstType.IsImplicitFrom(type); if (firstImplicitFromType != secondType.IsImplicitFrom(type)) { return(firstImplicitFromType ? -1 : 1); } } ConversionType convType = TypeExt.GetStandardConversion(firstType, secondType); if (convType == ConversionType.None) { if (firstType.IsSigned()) { if (secondType.IsUnsigned()) { return(-1); } } else if (firstType.IsUnsigned() && secondType.IsSigned()) { return(1); } return(0); } if (convType.IsExplicit() == firstImplicitFromType) { // secondType 可以隐式转换为 firstType。 return(1); } // firstType 可以隐式转换为 secondType。 return(-1); }