/// <summary> /// 基于参数类型,从给定的方法集中选择一个方法。 /// 允许通过指定 <see cref="BindingFlags.OptionalParamBinding"/> 来匹配可选参数。 /// </summary> /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param> /// <param name="match">用于匹配的候选方法集。</param> /// <param name="types">用于定位匹配方法的参数类型。</param> /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param> /// <returns>如果找到,则为匹配的方法;否则为 <c>null</c>。</returns> public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers) { if (match == null) { throw CommonExceptions.ArgumentNull("match"); } if (match.Length == 0) { throw CommonExceptions.CollectionEmpty("match"); } // 构造方法信息数组。 MatchInfo[] infos = new MatchInfo[match.Length]; MatchInfo info = null; int idx = 0; for (int i = 0; i < match.Length; i++) { if (match[i] != null) { info = new MatchInfo(match[i]); int len = info.Parameters.Length > types.Length ? info.Parameters.Length : types.Length; info.ParamOrder = info.ParamOrderRev = MethodExt.GetParamOrder(len); infos[idx++] = info; } } info = SelectMethod(bindingAttr, infos, idx, types); if (info == null) { return(null); } return(info.Method); }
/// <summary> /// 基于参数类型,从给定的方法集中选择一个方法。 /// 允许通过指定 <see cref="BindingFlags.OptionalParamBinding"/> 来匹配可选参数。 /// </summary> /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param> /// <param name="infos">用于匹配的候选方法信息集。</param> /// <param name="len">方法信息集合的长度。</param> /// <param name="types">用于定位匹配方法的参数类型。</param> /// <returns>如果找到,则为匹配的方法信息;否则为 <c>null</c>。</returns> private MatchInfo SelectMethod(BindingFlags bindingAttr, MatchInfo[] infos, int len, Type[] types) { bool optionalParamBinding = (bindingAttr & BindingFlags.OptionalParamBinding) != 0; int idx = 0; for (int i = 0; i < len; i++) { MatchInfo info = infos[i]; Type paramArrayType; if (MethodExt.CheckParameterCount(info.Parameters, types, info.ParamOrder, optionalParamBinding, out paramArrayType)) { info.ParamArrayType = paramArrayType; if (MakeGenericMethod(info, types) && CheckParameterType(info, types, optionalParamBinding)) { infos[idx++] = info; } } } if (idx == 0) { // 没有可匹配的方法。 return(null); } else if (idx == 1) { // 只有一个可匹配的方法。 return(infos[0]); } // 多个可匹配方法,寻找匹配的最好的方法。 int min = 0; bool ambig = false; for (int i = 1; i < idx; i++) { int cmp = FindMostSpecificMethod(infos[min], infos[i], types); if (cmp == 0) { ambig = true; } else if (cmp == 2) { min = i; ambig = false; } } if (ambig) { throw CommonExceptions.AmbiguousMatchMethod(); } return(infos[min]); }
/// <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> /// 基于指定的判据,从给定的属性集中选择一个属性。 /// </summary> /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param> /// <param name="match">用于匹配的候选属性集。</param> /// <param name="returnType">匹配属性必须具有的返回值。</param> /// <param name="indexes">所搜索的属性的索引类型。</param> /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param> /// <returns>如果找到,则为匹配的属性;否则为 <c>null</c>。</returns> public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers) { CommonExceptions.CheckArgumentNull(match, "match"); if (match.Length == 0) { return(null); } int idxLen = indexes == null ? 0 : indexes.Length; // 构造属性信息数组。 MatchInfo[] infos = new MatchInfo[match.Length]; int idx = 0; for (int i = 0; i < match.Length; i++) { if (match[i] != null) { ParameterInfo[] parameters = match[i].GetIndexParameters(); // 匹配属性类型与索引参数。 if (parameters.Length == idxLen && CheckParameters(infos[i], indexes, idxLen) && CanChangeType(match[i].PropertyType, returnType)) { infos[idx] = new MatchInfo(parameters, MethodExt.GetParamOrder(idxLen)); match[idx] = match[i]; idx++; } } } if (idx == 0) { return(null); } if (idx == 1) { return(match[0]); } // 多个可匹配属性,寻找匹配的最好的属性。 int min = 0; bool ambig = false; for (int i = 1; i < idx; i++) { // 先比较属性类型。 int cmp = FindMostSpecificType(match[min].PropertyType, match[i].PropertyType, returnType); if (cmp == 0 && indexes != null) { // 再比较属性参数。 cmp = FindMostSpecific(infos[min], infos[i], indexes); } if (cmp == 0) { // 最后比较定义的层级深度。 cmp = CompareHierarchyDepth(match[min], match[i]); if (cmp == 0) { ambig = true; } } if (cmp == 2) { ambig = false; min = i; } } if (ambig) { throw CommonExceptions.AmbiguousMatchProperty(); } return(match[min]); }
/// <summary> /// 基于提供的参数,从给定的方法集中选择要调用的方法。 /// </summary> /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param> /// <param name="match">用于匹配的候选方法集。</param> /// <param name="args">传入的参数。</param> /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param> /// <param name="culture">一个 <see cref="System.Globalization.CultureInfo"/> 实例, /// 用于在强制类型的联编程序实现中控制数据类型强制。</param> /// <param name="names">参数名(如果匹配时要考虑参数名)或 <c>null</c>(如果要将变量视为纯位置)。</param> /// <param name="state">方法返回之后,<paramref name="state"/> 包含一个联编程序提供的对象, /// 用于跟踪参数的重新排序。</param> /// <returns>匹配的方法。</returns> public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) { if (match == null) { throw CommonExceptions.ArgumentNull("match"); } if (match.Length == 0) { throw CommonExceptions.CollectionEmpty("match"); } // 检查参数名称数组,不能出现名称相同的两个参数。 if (names != null) { CheckNames(names); } // 构造方法信息数组。 MatchInfo[] infos = new MatchInfo[match.Length]; MatchInfo info = null; int idx = 0; for (int i = 0; i < match.Length; i++) { if (match[i] != null) { info = new MatchInfo(match[i]); int len = info.Parameters.Length > args.Length ? info.Parameters.Length : args.Length; if (names == null) { info.ParamOrder = info.ParamOrderRev = MethodExt.GetParamOrder(len); } else { info.ParamOrder = new int[len]; // 根据 names 创建参数顺序。 if (!CreateParamOrder(info.ParamOrder, info.Parameters, names)) { continue; } } infos[idx++] = info; } } if (idx == 0) { // 没有可匹配的方法。 state = null; return(null); } Type[] types = new Type[args.Length]; for (int i = 0; i < args.Length; i++) { // types[i] 为 null 表示可以匹配任何引用类型。 if (args[i] != null) { types[i] = args[i].GetType(); } } info = SelectMethod(bindingAttr, infos, idx, types); if (info == null) { // 没有可匹配的方法。 state = null; return(null); } UpdateArgs(info, ref args, names != null, out state); return(info.Method); }