Ejemplo n.º 1
0
        /// <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]);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 基于提供的参数,从给定的方法集中选择要调用的方法。
        /// </summary>
        /// <param name="bindingAttr"><see cref="BindingFlags"/> 值的按位组合。</param>
        /// <param name="match">用于匹配的候选方法集。</param>
        /// <param name="args">传入的参数。</param>
        /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param>
        /// <param name="culture">一个 <see cref="CultureInfo"/> 实例,
        /// 用于在强制类型的联编程序实现中控制数据类型强制。</param>
        /// <param name="names">参数名(如果匹配时要考虑参数名)或 <c>null</c>(如果要将变量视为纯位置)。</param>
        /// <param name="state">方法返回之后,<paramref name="state"/> 包含一个联编程序提供的对象,
        /// 用于跟踪参数的重新排序。</param>
        /// <returns>匹配的方法。</returns>
        /// <exception cref="ArgumentNullException"><paramref name="match"/> 为 <c>null</c>。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="args"/> 为 <c>null</c>。</exception>
        /// <exception cref="ArgumentException"><paramref name="match"/> 为空数组。</exception>
        /// <exception cref="ArgumentException"><paramref name="match"/> 中包含为 <c>null</c> 的元素。</exception>
        /// <exception cref="AmbiguousMatchException"><paramref name="match"/> 包含多个与 <paramref name="args"/>
        /// 匹配程度相同的方法。</exception>
        /// <exception cref="MissingFieldException"><paramref name="bindingAttr"/> 包含
        /// <see cref="BindingFlags.SetField"/>,且 <paramref name="match"/> 不包含任何可接受 <paramref name="args"/>
        /// 的方法。</exception>
        public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args,
                                                ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state)
        {
            CommonExceptions.CheckCollectionItemNull(match, "match");
            CommonExceptions.CheckArgumentNull(args, "args");
            if (names != null && names.Length > args.Length)
            {
                throw CommonExceptions.NamedParamTooBig("names");
            }
            Contract.EndContractBlock();
            // 检查参数名称数组,不能出现名称相同的参数。
            if (names != null && !names.IsDistinct(StringComparer.Ordinal))
            {
                throw CommonExceptions.DuplicateName("names");
            }
            MethodArgumentsOption options = MethodArgumentsOption.None;

            if (isExplicit)
            {
                options |= MethodArgumentsOption.Explicit;
            }
            if (bindingAttr.HasFlag(BindingFlags.OptionalParamBinding))
            {
                options |= MethodArgumentsOption.OptionalParamBinding;
            }
            int typesLen = args.Length;

            Type[] types = new Type[typesLen];
            for (int i = 0; i < typesLen; i++)
            {
                object arg = args[i];
                types[i] = arg == null ? null : arg.GetType();
            }
            MethodMatchInfo[] infos = new MethodMatchInfo[match.Length];
            MethodMatchInfo   info;
            int length = 0;

            for (int i = 0; i < match.Length; i++)
            {
                int[] paramOrder = null;
                if (names != null)
                {
                    paramOrder = CreateParamOrder(match[i], names, typesLen);
                    if (paramOrder == null)
                    {
                        continue;
                    }
                }
                info = MethodMatchInfo.GetMatchInfo(match[i], types, paramOrder, options);
                if (info != null)
                {
                    infos[length++] = info;
                }
            }
            if (length == 0)
            {
                // 没有可匹配的方法。
                state = null;
                throw CommonExceptions.MissingMethod();
            }
            info = SelectMethod(infos, length, types);
            if (info == null)
            {
                state = null;
                throw CommonExceptions.AmbiguousMatchMethod();
            }
            UpdateArgs(info, ref args, out state);
            return(info.Method);
        }