示例#1
0
		/// <summary>
		/// 对指定类型执行基本的类型转换判断,包括转换为 object 和 null 转换。
		/// 基本类型转换失败时,保证 value != null,nonNullableType != null。
		/// </summary>
		/// <param name="value">要转换的对象。</param>
		/// <param name="conversionType">要返回的对象的类型。</param>
		/// <param name="nonNullableType"><paramref name="value"/> 对应的 non-nullable-type。</param>
		/// <returns>如果基本类型转换成功,则为 <c>true</c>;否则为 <c>false</c>。</returns>
		private static bool BasicChangeType(ref object value, Type conversionType, out Type nonNullableType)
		{
			CommonExceptions.CheckArgumentNull(conversionType, "conversionType");
			if (conversionType.IsByRef)
			{
				conversionType = conversionType.GetElementType();
			}
			// 总是可以转换为 Object。
			if (conversionType == typeof(object))
			{
				nonNullableType = null;
				return true;
			}
			// value 为 null 的情况。
			bool nullableCType = TypeExt.IsNullableType(conversionType, out nonNullableType);
			if (value == null)
			{
				if (conversionType.IsValueType && !nullableCType)
				{
					throw CommonExceptions.CannotCastNullToValueType();
				}
				return true;
			}
			return false;
		}
示例#2
0
            /// <summary>
            /// 找到委托的参数列表,最后一个参数总是表示返回类型。
            /// </summary>
            /// <param name="paramTypes">处理器参数类型列表。</param>
            /// <param name="instanceType">实例的类型,如果不需要传入实例则为 <c>null</c>。</param>
            /// <returns>委托的参数列表。</returns>
            private static Type[] FindDelegateType(List <Type[]> paramTypes, Type instanceType)
            {
                Contract.Requires(paramTypes != null && paramTypes.Count > 0);
                int len = paramTypes[0].Length;

                Type[] types;
                if (instanceType == null)
                {
                    types = new Type[len];
                }
                else
                {
                    len++;
                    types    = new Type[len];
                    types[0] = instanceType;
                }
                int paramsIdx = paramTypes[0].Length - 1, typesIdx = len - 1;

                Contract.Assume(paramsIdx >= 0);
                int returnIdx = paramsIdx;

                types[typesIdx] = TypeExt.GetEncompassedType(paramTypes.Select(t => t[returnIdx])) ?? typeof(object);
                for (; paramsIdx >= 0; paramsIdx--, typesIdx--)
                {
                    int idx = paramsIdx;
                    types[typesIdx] = TypeExt.GetEncompassingType(paramTypes.Select(t => t[idx])) ?? typeof(object);
                }
                return(types);
            }
示例#3
0
        /// <summary>
        /// 返回从源类型到目标类型的用户定义的隐式转换方法。
        /// 该转换方法的参数与源类型和目标类型并不一定完全相同,但保证存在标准隐式转换。
        /// 不支持提升转换运算符,不允许两个类同时为 nullable 类型。
        /// </summary>
        /// <param name="sourceType">要获取用户定义的转换方法的源类型。</param>
        /// <param name="targetType">要获取用户定义的转换方法的目标类型。</param>
        /// <returns>如果存在从源类型到目标类型的用户定义的隐式转换方法,则返回该方法;
        /// 否则返回 <c>null</c>。</returns>
        public static ConversionMethod GetImplicitConversion(Type sourceType, Type targetType)
        {
            Debug.Assert(!(sourceType.IsNullableType() && targetType.IsNullableType()));
            Type exactSource = null, exactTarget = null;
            UniqueValue <ConversionMethod> method = new UniqueValue <ConversionMethod>();
            Conversion conv = GetTypeConversions(TypeExt.GetNonNullableType(targetType));

            for (int i = conv.ImplicitConvertFromIndex; i < conv.ConvertToIndex; i++)
            {
                ConversionMethod m = conv.Methods[i];
                if (m.SourceType.IsStandardImplicitFrom(sourceType))
                {
                    GetBestConversion(m, ref exactSource, ref exactTarget, method);
                }
            }
            if (!sourceType.IsNullableType())
            {
                conv = GetTypeConversions(sourceType);
                for (int i = conv.ImplicitConvertToIndex; i < conv.Methods.Length; i++)
                {
                    ConversionMethod m = conv.Methods[i];
                    if (targetType.IsStandardImplicitFrom(m.TargetType))
                    {
                        GetBestConversion(m, ref exactSource, ref exactTarget, method);
                    }
                }
            }
            if (method.IsUnique)
            {
                return(method.Value);
            }
            return(null);
        }
示例#4
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);
        }
示例#5
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);
        }