Beispiel #1
0
            /// <summary>
            /// 固定当前界限集所限定的类型参数。
            /// </summary>
            /// <returns>如果成功固定当前界限集的的类型参数,则为类型参数;
            /// 如果固定失败,则为 <c>null</c>。</returns>
            public Type FixTypeArg()
            {
                Type result;

                if (exactBound == null)
                {
                    var types = new HashSet <Type>(lowerBounds);
                    types.UnionWith(upperBounds);
                    types.RemoveWhere(type => !CanFixed(type));
                    if (types.Count == 0)
                    {
                        // 没有找到合适的推断结果。
                        return(null);
                    }
                    if (types.Count == 1)
                    {
                        // 找到唯一的推断结果。
                        result = types.First();
                    }
                    else
                    {
                        // 进一步进行推断。
                        result = TypeExt.GetEncompassingType(types);
                        if (result == null)
                        {
                            return(null);
                        }
                    }
                }
                else
                {
                    result = exactBound;
                }
                // 判断引用类型约束。
                if (ReferenceType && result.IsValueType)
                {
                    return(null);
                }
                return(result);
            }
Beispiel #2
0
        /// <summary>
        /// 根据给定的类型数组推断泛型方法的类型参数。
        /// </summary>
        /// <param name="method">要推断类型参数的泛型方法。</param>
        /// <param name="parameters">泛型方法的形参参数数组。</param>
        /// <param name="types">实参参数数组。</param>
        /// <returns>如果成功推断泛型方法的类型参数,则为类型参数数组;
        /// 如果推断失败或给定的方法不是泛型方法定义,则为 <c>null</c>。</returns>
        internal static Type[] GenericArgumentsInferences(this MethodBase method,
                                                          ParameterInfo[] parameters, Type[] types)
        {
            Debug.Assert(method.IsGenericMethodDefinition);
            Debug.Assert(parameters != null);
            Debug.Assert(types != null);
            int len = parameters.Length > types.Length ? parameters.Length : types.Length;

            int[] paramOrder = GetParamOrder(len);
            Type  paramArrayType;

            if (CheckParameterCount(parameters, types, paramOrder, true, out paramArrayType))
            {
                Type[] paramTypes = new Type[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    paramTypes[i] = parameters[i].ParameterType;
                }
                return(TypeExt.GenericArgumentsInferences(method.GetGenericArguments(), paramTypes,
                                                          ref paramArrayType, types, paramOrder));
            }
            return(null);
        }
Beispiel #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);
        }
Beispiel #4
0
        /// <summary>
        /// 寻找与 <paramref name="type"/> 匹配的最好的类型。调用保证 <paramref name="type"/>
        /// 可以转换为 <paramref name="firstType"/> 和 <paramref name="secondType"/>。
        /// </summary>
        /// <param name="firstType">要比较匹配的第一个类型。</param>
        /// <param name="secondType">要比较匹配的第二个类型。</param>
        /// <param name="type">要进行匹配的类型。</param>
        /// <returns>如果 <paramref name="firstType"/> 与 <paramref name="type"/> 匹配的更好,则为 <c>-1</c>;
        /// 如果 <paramref name="secondType"/> 与 <paramref name="type"/> 匹配的更好,则为 <c>1</c>;
        /// 如果匹配程度相同,则为 <c>0</c>。</returns>
        /// <remarks>《CSharp Language Specification》 7.5.3.3 Better conversion from expression。</remarks>
        private int CompareType(Type firstType, Type secondType, Type type)
        {
            Contract.Requires(firstType != null && secondType != null && type != null);
            Contract.Ensures(Contract.Result <int>() >= -1 && Contract.Result <int>() <= 1);
            if (firstType == secondType)
            {
                return(0);
            }
            if (firstType == type)
            {
                return(-1);
            }
            if (secondType == type)
            {
                return(1);
            }
            bool typeByRef = type.IsByRef;

            // 根据 type 是否按引用传递,选择普通参数或按引用传递的参数。
            if (firstType.IsByRef)
            {
                firstType = firstType.GetElementType();
                if (secondType.IsByRef)
                {
                    secondType = secondType.GetElementType();
                }
                else if (firstType == secondType)
                {
                    return(typeByRef ? -1 : 1);
                }
            }
            else if (secondType.IsByRef)
            {
                secondType = secondType.GetElementType();
                if (firstType == secondType)
                {
                    return(typeByRef ? 1 : -1);
                }
            }
            if (typeByRef)
            {
                type = type.GetElementType();
            }
            bool firstImplicitFromType = true;

            if (isExplicit)
            {
                // 可以从 type 隐式转换的类型会更匹配,仅当允许显式类型转换时才需要检测。
                firstImplicitFromType = firstType.IsImplicitFrom(type);
                if (firstImplicitFromType != secondType.IsImplicitFrom(type))
                {
                    return(firstImplicitFromType ? -1 : 1);
                }
            }
            ConversionType convType = TypeExt.GetStandardConversion(firstType, secondType);

            if (convType == ConversionType.None)
            {
                if (firstType.IsSigned())
                {
                    if (secondType.IsUnsigned())
                    {
                        return(-1);
                    }
                }
                else if (firstType.IsUnsigned() && secondType.IsSigned())
                {
                    return(1);
                }
                return(0);
            }
            if (convType.IsExplicit() == firstImplicitFromType)
            {
                // secondType 可以隐式转换为 firstType。
                return(1);
            }
            // firstType 可以隐式转换为 secondType。
            return(-1);
        }