Example #1
0
        /// <summary>
        /// 基于参数类型,从给定的方法集中选择一个方法。
        /// 允许通过指定 <see cref="BindingFlags.OptionalParamBinding"/> 来匹配可选参数。
        /// </summary>
        /// <param name="bindingAttr"><see cref="BindingFlags"/> 值的按位组合。</param>
        /// <param name="match">用于匹配的候选方法集。</param>
        /// <param name="types">用于定位匹配方法的参数类型。</param>
        /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param>
        /// <returns>如果找到,则为匹配的方法;否则为 <c>null</c>。</returns>
        /// <exception cref="ArgumentNullException"><paramref name="match"/> 为 <c>null</c>。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="types"/> 为 <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="types"/>
        /// 匹配程度相同的方法。</exception>
        /// <remarks>此方法支持可选参数,可以通过为参数类型指定 <see cref="Missing"/> 来表示使用可选参数。
        /// 或者为 <paramref name="bindingAttr"/> 设置 <see cref="BindingFlags.InvokeMethod"/>、
        /// <see cref="BindingFlags.CreateInstance"/>、<see cref="BindingFlags.GetProperty"/> 或
        /// <see cref="BindingFlags.SetProperty"/> 之一,就可以直接省略掉可选参数对应的类型。</remarks>
        public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types,
                                                ParameterModifier[] modifiers)
        {
            CommonExceptions.CheckCollectionItemNull(match, "match");
            CommonExceptions.CheckArgumentNull(types, "types");
            Contract.EndContractBlock();
            MethodArgumentsOption options = MethodArgumentsOption.None;

            if (isExplicit)
            {
                options |= MethodArgumentsOption.Explicit;
            }
            if (bindingAttr.HasFlag(BindingFlags.OptionalParamBinding))
            {
                options |= MethodArgumentsOption.OptionalParamBinding;
            }
            MethodMatchInfo[] infos = new MethodMatchInfo[match.Length];
            MethodMatchInfo   info;
            int length = 0;

            for (int i = 0; i < match.Length; i++)
            {
                info = MethodMatchInfo.GetMatchInfo(match[i], types, null, options);
                if (info != null)
                {
                    infos[length++] = info;
                }
            }
            info = SelectMethod(infos, length, types);
            return(info == null ? null : info.Method);
        }
Example #2
0
            /// <summary>
            /// 返回指定方法的匹配信息。
            /// </summary>
            /// <param name="method">要进行匹配的方法。</param>
            /// <param name="types">方法的预期参数列表,使用 <c>null</c> 表示引用类型约束,<see cref="Missing"/>
            /// 表示使用默认值。</param>
            /// <param name="paramOrder">方法的参数顺序列表,使用 <c>paramOrder[i]</c> 表示 <c>indexes[i]</c>
            /// 的实际参数位置,其长度大于等于 <paramref name="types"/> 的长度。如果为 <c>null</c> 则表示使用默认顺序。</param>
            /// <param name="options">方法参数的选项。</param>
            /// <returns><paramref name="method"/> 的匹配信息,如果不能进行匹配则为 <c>null</c>。</returns>
            public static MethodMatchInfo GetMatchInfo(MethodBase method, Type[] types,
                                                       int[] paramOrder, MethodArgumentsOption options)
            {
                Contract.Requires(method != null && types != null);
                Contract.Requires(paramOrder == null || paramOrder.Length >= types.Length);
                // 修正 indexes 的格式。
                var parameters = method.GetParametersNoCopy();

                if (paramOrder == null)
                {
                    types = types.Extend(parameters.Length, typeof(Missing));
                }
                else
                {
                    var typeLen  = types.Length;
                    var newTypes = new Type[typeLen > parameters.Length ? typeLen : parameters.Length];
                    newTypes.Fill(typeof(Missing));
                    for (var i = 0; i < typeLen; i++)
                    {
                        newTypes[paramOrder[i]] = types[i];
                    }
                    types = newTypes;
                }
                MethodArgumentsInfo argsInfo;

                // 对泛型方法进行泛型类型推断。
                if (method.IsGenericMethodDefinition)
                {
                    var declaringType = method.DeclaringType;
                    if (declaringType != null && declaringType.ContainsGenericParameters)
                    {
                        return(null);
                    }
                    argsInfo = method.GenericArgumentsInferences(null, types, options);
                    if (argsInfo == null)
                    {
                        return(null);
                    }
                    method = ((MethodInfo)method).MakeGenericMethod(argsInfo.GenericArguments);
                    argsInfo.UpdateParamArrayType(method);
                }
                else
                {
                    argsInfo = MethodArgumentsInfo.GetInfo(method, types, options);
                }
                if (argsInfo == null)
                {
                    return(null);
                }
                if (argsInfo.OptionalArgumentTypes != null)
                {
                    // 动态调用不支持可变参数。
                    return(null);
                }
                return(new MethodMatchInfo(method, argsInfo, paramOrder));
            }
Example #3
0
 /// <summary>
 /// 根据给定的方法实参类型数组推断泛型方法的泛型类型。
 /// </summary>
 /// <param name="method">要推断泛型类型的泛型方法定义。</param>
 /// <param name="types">方法实参类型数组。</param>
 /// <param name="options">泛型类型推断的选项。</param>
 /// <returns>如果成功推断泛型方法的类型参数,则为推断结果;否则为 <c>null</c>。</returns>
 /// <exception cref="ArgumentNullException"><paramref name="method"/> 为 <c>null</c>。</exception>
 /// <exception cref="ArgumentNullException"><paramref name="types"/> 为 <c>null</c>。</exception>
 /// <exception cref="InvalidOperationException">当前 <see cref="MethodInfo"/> 不表示泛型方法定义。
 /// 也就是说,<see cref="MethodBase.IsGenericMethodDefinition "/> 返回 <c>false</c>。</exception>
 public static Type[] GenericArgumentsInferences(this MethodBase method, Type[] types,
     MethodArgumentsOption options)
 {
     CommonExceptions.CheckArgumentNull(method, "method");
     CommonExceptions.CheckArgumentNull(types, "types");
     Contract.EndContractBlock();
     if (!method.IsGenericMethodDefinition)
     {
         throw CommonExceptions.NeedGenericMethodDefinition("method");
     }
     var result = GenericArgumentsInferences(method, null, types, options);
     return result == null ? null : result.GenericArguments;
 }
Example #4
0
        /// <summary>
        /// 根据给定的方法实参类型数组推断泛型方法的泛型类型。
        /// </summary>
        /// <param name="method">要推断泛型类型的泛型方法定义。</param>
        /// <param name="types">方法实参类型数组。</param>
        /// <param name="options">泛型类型推断的选项。</param>
        /// <returns>如果成功推断泛型方法的类型参数,则为推断结果;否则为 <c>null</c>。</returns>
        /// <exception cref="ArgumentNullException"><paramref name="method"/> 为 <c>null</c>。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="types"/> 为 <c>null</c>。</exception>
        /// <exception cref="InvalidOperationException">当前 <see cref="MethodInfo"/> 不表示泛型方法定义。
        /// 也就是说,<see cref="MethodBase.IsGenericMethodDefinition "/> 返回 <c>false</c>。</exception>
        public static Type[] GenericArgumentsInferences(this MethodBase method, Type[] types,
                                                        MethodArgumentsOption options)
        {
            CommonExceptions.CheckArgumentNull(method, "method");
            CommonExceptions.CheckArgumentNull(types, "types");
            Contract.EndContractBlock();
            if (!method.IsGenericMethodDefinition)
            {
                throw CommonExceptions.NeedGenericMethodDefinition("method");
            }
            var result = GenericArgumentsInferences(method, null, types, options);

            return(result == null ? null : result.GenericArguments);
        }
Example #5
0
        /// <summary>
        /// 根据实参参数类型推断当前泛型方法定义的类型参数,
        /// 并返回表示结果封闭构造方法的 <see cref="MethodInfo"/> 对象。
        /// </summary>
        /// <param name="method">要进行类型参数推断的泛型方法定义。</param>
        /// <param name="types">泛型方法的实参参数数组。</param>
        /// <param name="options">泛型类型推断的选项。</param>
        /// <returns>一个 <see cref="MethodInfo"/> 对象,表示通过将当前泛型方法定义的类型参数替换为根据
        /// <paramref name="types"/> 推断得到的元素生成的封闭构造方法。</returns>
        /// <exception cref="InvalidOperationException">当前 <see cref="MethodInfo"/> 不表示泛型方法定义。
        /// 也就是说,<see cref="MethodBase.IsGenericMethodDefinition "/> 返回 <c>false</c>。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="method"/> 为 <c>null</c>。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="types"/> 为 <c>null</c>。</exception>
        /// <exception cref="ArgumentException">不能从 <paramref name="types"/> 推断得到类型参数。</exception>
        /// <exception cref="ArgumentException">根据 <paramref name="types"/>
        /// 推断出来的类型参数中的某个元素不满足为当前泛型方法定义的相应类型参数指定的约束。</exception>
        public static MethodInfo MakeGenericMethodFromParamTypes(this MethodInfo method, Type[] types,
                                                                 MethodArgumentsOption options)
        {
            CommonExceptions.CheckArgumentNull(method, "method");
            CommonExceptions.CheckArgumentNull(types, "types");
            Contract.Ensures(Contract.Result <MethodInfo>() != null);
            if (!method.IsGenericMethodDefinition)
            {
                throw CommonExceptions.NeedGenericMethodDefinition("method");
            }
            var result = GenericArgumentsInferences(method, null, types, options);

            if (result == null)
            {
                throw CommonExceptions.CannotInferenceGenericArguments("method");
            }
            return(method.MakeGenericMethod(result.GenericArguments));
        }
Example #6
0
        /// <summary>
        /// 返回方法的参数信息。
        /// </summary>
        /// <param name="method">要获取参数信息的方法。</param>
        /// <param name="types">方法实参类型数组,其长度必须大于等于方法的参数个数。
        /// 使用 <see cref="Missing"/> 表示无需进行类型检查,<c>null</c> 表示引用类型标志。</param>
        /// <param name="options">方法参数信息的选项。</param>
        /// <returns>方法的参数信息。</returns>
        public static MethodArgumentsInfo GetInfo(MethodBase method, Type[] types, MethodArgumentsOption options)
        {
            Contract.Requires(method != null && types != null);
            MethodArgumentsInfo result = new MethodArgumentsInfo(method, types);
            bool optionalParamBinding  = options.HasFlag(MethodArgumentsOption.OptionalParamBinding);
            bool isExplicit            = options.HasFlag(MethodArgumentsOption.Explicit);
            bool convertRefType        = options.HasFlag(MethodArgumentsOption.ConvertRefType);
            // 填充方法实例。
            int offset = 0;

            if (options.HasFlag(MethodArgumentsOption.ContainsInstance))
            {
                if (!result.MarkInstanceType(isExplicit, convertRefType))
                {
                    return(null);
                }
                offset++;
            }
            // 填充 params 参数和可变参数。
            if (!result.FillParamArray(isExplicit, convertRefType))
            {
                return(null);
            }
            // 检查实参是否与形参对应,未对应的参数是否包含默认值。
            ParameterInfo[] parameters = method.GetParametersNoCopy();
            int             paramLen   = parameters.Length;

            if (result.ParamArrayType != null)
            {
                paramLen--;
                Contract.Assume(paramLen >= 0);
            }
            for (int i = 0, j = offset; i < paramLen; i++, j++)
            {
                if (!CheckParameter(parameters[i], types[j], optionalParamBinding, isExplicit, convertRefType))
                {
                    return(null);
                }
            }
            result.fixedArguments = new ArrayAdapter <Type>(types, offset, paramLen);
            return(result);
        }
Example #7
0
        /// <summary>
        /// 获取指定方法的参数信息。
        /// </summary>
        /// <param name="method">要获取参数信息的方法。</param>
        /// <param name="types">方法的实参类型列表。</param>
        /// <param name="returnType">方法的返回值类型。</param>
        /// <returns>方法的参数信息。</returns>
        private static MethodArgumentsInfo GetArgumentsInfo(ref MethodBase method, Type[] types, Type returnType)
        {
            MethodArgumentsOption options = MethodArgumentsOption.OptionalAndExplicit | MethodArgumentsOption.ConvertRefType;

            if (!method.IsStatic && !(method is ConstructorInfo))
            {
                options |= MethodArgumentsOption.ContainsInstance;
            }
            if (method.IsGenericMethodDefinition)
            {
                // 对泛型方法定义进行类型推断。
                MethodArgumentsInfo argumentsInfo = method.GenericArgumentsInferences(returnType, types, options);
                if (argumentsInfo == null)
                {
                    return(null);
                }
                method = ((MethodInfo)method).MakeGenericMethod(argumentsInfo.GenericArguments);
                argumentsInfo.UpdateParamArrayType(method);
                return(argumentsInfo);
            }
            // 调用时保证 !member.ContainsGenericParameters。
            return(MethodArgumentsInfo.GetInfo(method, types, options));
        }
Example #8
0
        /// <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);
        }
Example #9
0
 /// <summary>
 /// 返回方法的参数信息。
 /// </summary>
 /// <param name="method">要获取参数信息的方法。</param>
 /// <param name="types">方法实参类型数组,其长度必须大于等于方法的参数个数。
 /// 使用 <see cref="Missing"/> 表示无需进行类型检查,<c>null</c> 表示引用类型标志。</param>
 /// <param name="options">方法参数信息的选项。</param>
 /// <returns>方法的参数信息。</returns>
 public static MethodArgumentsInfo GetInfo(MethodBase method, Type[] types, MethodArgumentsOption options)
 {
     Contract.Requires(method != null && types != null);
     MethodArgumentsInfo result = new MethodArgumentsInfo(method, types);
     bool optionalParamBinding = options.HasFlag(MethodArgumentsOption.OptionalParamBinding);
     bool isExplicit = options.HasFlag(MethodArgumentsOption.Explicit);
     bool convertRefType = options.HasFlag(MethodArgumentsOption.ConvertRefType);
     // 填充方法实例。
     int offset = 0;
     if (options.HasFlag(MethodArgumentsOption.ContainsInstance))
     {
         if (!result.MarkInstanceType(isExplicit, convertRefType))
         {
             return null;
         }
         offset++;
     }
     // 填充 params 参数和可变参数。
     if (!result.FillParamArray(isExplicit, convertRefType))
     {
         return null;
     }
     // 检查实参是否与形参对应,未对应的参数是否包含默认值。
     ParameterInfo[] parameters = method.GetParametersNoCopy();
     int paramLen = parameters.Length;
     if (result.ParamArrayType != null)
     {
         paramLen--;
         Contract.Assume(paramLen >= 0);
     }
     for (int i = 0, j = offset; i < paramLen; i++, j++)
     {
         if (!CheckParameter(parameters[i], types[j], optionalParamBinding, isExplicit, convertRefType))
         {
             return null;
         }
     }
     result.fixedArguments = new ArrayAdapter<Type>(types, offset, paramLen);
     return result;
 }
Example #10
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);
        }
Example #11
0
 /// <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;
 }
Example #12
0
 /// <summary>
 /// 根据实参参数类型推断当前泛型方法定义的类型参数,
 /// 并返回表示结果封闭构造方法的 <see cref="MethodInfo"/> 对象。
 /// </summary>
 /// <param name="method">要进行类型参数推断的泛型方法定义。</param>
 /// <param name="types">泛型方法的实参参数数组。</param>
 /// <param name="options">泛型类型推断的选项。</param>
 /// <returns>一个 <see cref="MethodInfo"/> 对象,表示通过将当前泛型方法定义的类型参数替换为根据 
 /// <paramref name="types"/> 推断得到的元素生成的封闭构造方法。</returns>
 /// <exception cref="InvalidOperationException">当前 <see cref="MethodInfo"/> 不表示泛型方法定义。
 /// 也就是说,<see cref="MethodBase.IsGenericMethodDefinition "/> 返回 <c>false</c>。</exception>
 /// <exception cref="ArgumentNullException"><paramref name="method"/> 为 <c>null</c>。</exception>
 /// <exception cref="ArgumentNullException"><paramref name="types"/> 为 <c>null</c>。</exception>
 /// <exception cref="ArgumentException">不能从 <paramref name="types"/> 推断得到类型参数。</exception>
 /// <exception cref="ArgumentException">根据 <paramref name="types"/>
 /// 推断出来的类型参数中的某个元素不满足为当前泛型方法定义的相应类型参数指定的约束。</exception>
 public static MethodInfo MakeGenericMethodFromParamTypes(this MethodInfo method, Type[] types,
     MethodArgumentsOption options)
 {
     CommonExceptions.CheckArgumentNull(method, "method");
     CommonExceptions.CheckArgumentNull(types, "types");
     Contract.Ensures(Contract.Result<MethodInfo>() != null);
     if (!method.IsGenericMethodDefinition)
     {
         throw CommonExceptions.NeedGenericMethodDefinition("method");
     }
     var result = GenericArgumentsInferences(method, null, types, options);
     if (result == null)
     {
         throw CommonExceptions.CannotInferenceGenericArguments("method");
     }
     return method.MakeGenericMethod(result.GenericArguments);
 }