Пример #1
0
        /// <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)
        {
            ExceptionHelper.CheckArrayEmpty(match, "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);
        }
Пример #2
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 ExceptionHelper.AmbiguousMatchMethod();
            }
            return(infos[min]);
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        /// <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)
        {
            ExceptionHelper.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 ExceptionHelper.AmbiguousMatchProperty();
            }
            return(match[min]);
        }
Пример #5
0
        /// <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)
        {
            ExceptionHelper.CheckArrayEmpty(match, "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);
        }