/// <summary> /// 使用要复制的泛型形参的界限集集合初始化 <see cref="TypeBounds"/> 类的新实例。 /// </summary> /// <param name="typeBounds">泛型形参的界限集集合。</param> public TypeBounds(TypeBounds typeBounds) { Contract.Requires(typeBounds != null); int len = typeBounds.boundSets.Length; this.boundSets = new BoundSet[len]; this.boundSetDict = new Dictionary<Type, BoundSet>(len); for (int i = 0; i < typeBounds.boundSets.Length; i++) { this.boundSets[i] = new BoundSet(typeBounds.boundSets[i]); this.boundSetDict.Add(this.boundSets[i].GenericArgument, this.boundSets[i]); } }
/// <summary> /// 使用要复制的泛型形参的界限集集合初始化 <see cref="TypeBounds"/> 类的新实例。 /// </summary> /// <param name="typeBounds">泛型形参的界限集集合。</param> public TypeBounds(TypeBounds typeBounds) { Contract.Requires(typeBounds != null); var len = typeBounds.boundSets.Length; boundSets = new BoundSet[len]; boundSetDict = new Dictionary <Type, BoundSet>(len); for (var i = 0; i < typeBounds.boundSets.Length; i++) { boundSets[i] = new BoundSet(typeBounds.boundSets[i]); boundSetDict.Add(boundSets[i].GenericArgument, boundSets[i]); } }
/// <summary> /// 使用要复制的泛型形参的界限集集合初始化 <see cref="TypeBounds"/> 类的新实例。 /// </summary> /// <param name="typeBounds">泛型形参的界限集集合。</param> public TypeBounds(TypeBounds typeBounds) { Contract.Requires(typeBounds != null); int len = typeBounds.boundSets.Length; this.boundSets = new BoundSet[len]; this.boundSetDict = new Dictionary <Type, BoundSet>(len); for (int i = 0; i < typeBounds.boundSets.Length; i++) { this.boundSets[i] = new BoundSet(typeBounds.boundSets[i]); this.boundSetDict.Add(this.boundSets[i].GenericArgument, this.boundSets[i]); } }
/// <summary> /// 检查方法的返回类型。 /// </summary> /// <param name="method">要推断泛型类型的泛型方法定义。</param> /// <param name="returnType">方法的实际返回类型,如果不存在则传入 <c>null</c>。</param> /// <param name="bounds">界限集集合。</param> /// <param name="isExplicit">类型检查时,如果考虑显式类型转换,则为 <c>true</c>; /// 否则只考虑隐式类型转换。</param> /// <returns>如果成功检查返回类型,则为 <c>true</c>;否则为 <c>false</c>。</returns> private static bool CheckReturnType(MethodBase method, Type returnType, TypeBounds bounds, bool isExplicit) { Contract.Requires(method != null && bounds != null); if (returnType == null) { return(true); } MethodInfo methodInfo = method as MethodInfo; if (methodInfo == null) { return(true); } Type type = methodInfo.ReturnType; if (type.ContainsGenericParameters) { // 对方法返回类型进行上限推断。 return(bounds.TypeInferences(type, returnType, true)); } return(returnType.IsConvertFrom(type, isExplicit)); }
/// <summary> /// 根据给定的方法实参类型数组推断泛型方法的泛型类型。 /// </summary> /// <param name="method">要推断泛型类型的泛型方法定义。</param> /// <param name="returnType">方法的实际返回类型,如果不存在则传入 <c>null</c>。</param> /// <param name="types">方法实参类型数组。</param> /// <param name="options">方法参数信息的选项。</param> /// <returns>如果成功推断泛型方法的类型参数,则为推断结果;否则为 <c>null</c>。</returns> /// <remarks>得到的结果中,<see cref="MethodArgumentsInfo.ParamArrayType"/> 可能包含泛型类型参数。</remarks> internal static MethodArgumentsInfo GenericArgumentsInferences(this MethodBase method, Type returnType, Type[] types, MethodArgumentsOption options) { Contract.Requires(method != null && types != null); ParameterInfo[] parameters = method.GetParametersNoCopy(); // 提取方法参数信息。 types = types.Extend(parameters.Length, typeof(Missing)); MethodArgumentsInfo result = MethodArgumentsInfo.GetInfo(method, types, options); if (result == null) { return(null); } // 对方法返回值进行推断。 bool isExplicit = options.HasFlag(MethodArgumentsOption.Explicit); TypeBounds bounds = new TypeBounds(method.GetGenericArguments()); if (!CheckReturnType(method, returnType, bounds, isExplicit)) { return(null); } // 对方法固定参数进行推断。 int paramLen = result.FixedArguments.Count; for (int i = 0; i < paramLen; i++) { Type paramType = parameters[i].ParameterType; Type argType = result.FixedArguments[i]; if (paramType.ContainsGenericParameters && argType != typeof(Missing) && !bounds.TypeInferences(paramType, argType)) { return(null); } } IList <Type> paramArgTypes = result.ParamArgumentTypes; if (result.ParamArrayType == null || paramArgTypes.Count == 0) { Type[] args = bounds.FixTypeArguments(); if (args == null) { return(null); } result.GenericArguments = args; return(result); } // 对 params 参数进行推断。 Type paramElementType = result.ParamArrayType.GetElementType(); int paramArgCnt = paramArgTypes.Count; if (paramArgCnt > 1) { // 多个实参对应一个形参,做多次类型推断。 for (int i = 0; i < paramArgCnt; i++) { if (paramArgTypes[i] != typeof(Missing) && !bounds.TypeInferences(paramElementType, paramArgTypes[i])) { return(null); } } Type[] args = bounds.FixTypeArguments(); if (args == null) { return(null); } result.GenericArguments = args; return(result); } // 一个实参对应一个形参,需要判断是否需要展开 params 参数。 TypeBounds newBounds = new TypeBounds(bounds); Type type = paramArgTypes[0]; // 首先尝试对 paramArrayType 进行推断。 if (type == typeof(Missing) || bounds.TypeInferences(result.ParamArrayType, type)) { Type[] args = bounds.FixTypeArguments(); if (args != null) { // 推断成功的话,则无需展开 params 参数。 result.ClearParamArrayType(); result.GenericArguments = args; return(result); } } // 然后尝试对 paramElementType 进行推断。 if (newBounds.TypeInferences(paramElementType, type)) { Type[] args = newBounds.FixTypeArguments(); if (args == null) { return(null); } result.GenericArguments = args; return(result); } return(null); }
/// <summary> /// 检查方法的返回类型。 /// </summary> /// <param name="method">要推断泛型类型的泛型方法定义。</param> /// <param name="returnType">方法的实际返回类型,如果不存在则传入 <c>null</c>。</param> /// <param name="bounds">界限集集合。</param> /// <param name="isExplicit">类型检查时,如果考虑显式类型转换,则为 <c>true</c>; /// 否则只考虑隐式类型转换。</param> /// <returns>如果成功检查返回类型,则为 <c>true</c>;否则为 <c>false</c>。</returns> private static bool CheckReturnType(MethodBase method, Type returnType, TypeBounds bounds, bool isExplicit) { Contract.Requires(method != null && bounds != null); if (returnType == null) { return true; } MethodInfo methodInfo = method as MethodInfo; if (methodInfo == null) { return true; } Type type = methodInfo.ReturnType; if (type.ContainsGenericParameters) { // 对方法返回类型进行上限推断。 return bounds.TypeInferences(type, returnType, true); } return returnType.IsConvertFrom(type, isExplicit); }
/// <summary> /// 根据给定的方法实参类型数组推断泛型方法的泛型类型。 /// </summary> /// <param name="method">要推断泛型类型的泛型方法定义。</param> /// <param name="returnType">方法的实际返回类型,如果不存在则传入 <c>null</c>。</param> /// <param name="types">方法实参类型数组。</param> /// <param name="options">方法参数信息的选项。</param> /// <returns>如果成功推断泛型方法的类型参数,则为推断结果;否则为 <c>null</c>。</returns> /// <remarks>得到的结果中,<see cref="MethodArgumentsInfo.ParamArrayType"/> 可能包含泛型类型参数。</remarks> internal static MethodArgumentsInfo GenericArgumentsInferences(this MethodBase method, Type returnType, Type[] types, MethodArgumentsOption options) { Contract.Requires(method != null && types != null); ParameterInfo[] parameters = method.GetParametersNoCopy(); // 提取方法参数信息。 types = types.Extend(parameters.Length, typeof(Missing)); MethodArgumentsInfo result = MethodArgumentsInfo.GetInfo(method, types, options); if (result == null) { return null; } // 对方法返回值进行推断。 bool isExplicit = options.HasFlag(MethodArgumentsOption.Explicit); TypeBounds bounds = new TypeBounds(method.GetGenericArguments()); if (!CheckReturnType(method, returnType, bounds, isExplicit)) { return null; } // 对方法固定参数进行推断。 int paramLen = result.FixedArguments.Count; for (int i = 0; i < paramLen; i++) { Type paramType = parameters[i].ParameterType; Type argType = result.FixedArguments[i]; if (paramType.ContainsGenericParameters && argType != typeof(Missing) && !bounds.TypeInferences(paramType, argType)) { return null; } } IList<Type> paramArgTypes = result.ParamArgumentTypes; if (result.ParamArrayType == null || paramArgTypes.Count == 0) { Type[] args = bounds.FixTypeArguments(); if (args == null) { return null; } result.GenericArguments = args; return result; } // 对 params 参数进行推断。 Type paramElementType = result.ParamArrayType.GetElementType(); int paramArgCnt = paramArgTypes.Count; if (paramArgCnt > 1) { // 多个实参对应一个形参,做多次类型推断。 for (int i = 0; i < paramArgCnt; i++) { if (paramArgTypes[i] != typeof(Missing) && !bounds.TypeInferences(paramElementType, paramArgTypes[i])) { return null; } } Type[] args = bounds.FixTypeArguments(); if (args == null) { return null; } result.GenericArguments = args; return result; } // 一个实参对应一个形参,需要判断是否需要展开 params 参数。 TypeBounds newBounds = new TypeBounds(bounds); Type type = paramArgTypes[0]; // 首先尝试对 paramArrayType 进行推断。 if (type == typeof(Missing) || bounds.TypeInferences(result.ParamArrayType, type)) { Type[] args = bounds.FixTypeArguments(); if (args != null) { // 推断成功的话,则无需展开 params 参数。 result.ClearParamArrayType(); result.GenericArguments = args; return result; } } // 然后尝试对 paramElementType 进行推断。 if (newBounds.TypeInferences(paramElementType, type)) { Type[] args = newBounds.FixTypeArguments(); if (args == null) { return null; } result.GenericArguments = args; return result; } return null; }