Exemple #1
0
		/// <summary>
		/// 返回指定类型的对象,其值等效于指定对象。参数提供区域性特定的格式设置信息。
		/// 只对允许进行隐式类型转换。
		/// </summary>
		/// <param name="value">要转换的对象。</param>
		/// <param name="conversionType">要返回的对象的类型。</param>
		/// <param name="provider">一个提供区域性特定的格式设置信息的对象。</param>
		/// <returns>一个对象,其类型为 <paramref name="conversionType"/>,
		/// 并且其值等效于 <paramref name="value"/>。</returns>
		internal static object ImplicitChangeType(object value, Type conversionType, IFormatProvider provider)
		{
			Type nonNullableType;
			if (BasicChangeType(ref value, conversionType, out nonNullableType))
			{
				return value;
			}
			Type type = value.GetType();
			// 尝试标准隐式类型转换。
			bool success;
			object result = StandardImplicitChangeType(value, type, nonNullableType, provider, out success);
			if (success)
			{
				return result;
			}
			// 对隐式类型转换运算符进行判断。
			ConversionMethod method = ConversionCache.GetImplicitConversion(type, conversionType);
			if (method != null)
			{
				value = MethodInfo.GetMethodFromHandle(method.Method).Invoke(null, new object[] { value });
				if (value != null)
				{
					type = value.GetType();
					if (type != nonNullableType)
					{
						// 处理用户定义隐式类型转换之后的标准隐式类型转换。
						value = StandardImplicitChangeType(value, type, nonNullableType, provider, out success);
					}
				}
				return value;
			}
			throw CommonExceptions.ConvertInvalidValue(value, conversionType);
		}
Exemple #2
0
 /// <summary>
 /// 根据给定的用户定义转换获取最合适的转换。
 /// </summary>
 /// <param name="method">要测试的用户定义转换。</param>
 /// <param name="exactSource">当前最合适的源类型。</param>
 /// <param name="exactTarget">当前最合适的目标类型。</param>
 /// <param name="uniqueMethod">最合适的转换。</param>
 private static void GetBestConversion(ConversionMethod method, ref Type exactSource, ref Type exactTarget,
                                       UniqueValue <ConversionMethod> uniqueMethod)
 {
     if (exactSource != method.SourceType)
     {
         if (exactSource != null && method.SourceType.IsAssignableFrom(exactSource))
         {
             return;
         }
         else
         {
             exactSource = method.SourceType;
             uniqueMethod.Reset();
         }
     }
     if (exactTarget != method.TargetType)
     {
         if (exactTarget != null && exactTarget.IsAssignableFrom(method.TargetType))
         {
             return;
         }
         else
         {
             exactTarget = method.TargetType;
             uniqueMethod.Reset();
         }
     }
     uniqueMethod.Value = method;
 }
Exemple #3
0
        /// <summary>
        /// 返回从源类型到目标类型的用户定义的显式转换方法。
        /// 该转换方法的参数与源类型和目标类型并不一定完全相同,但保证存在标准显式转换。
        /// </summary>
        /// <param name="sourceType">要获取用户定义的转换方法的源类型。</param>
        /// <param name="targetType">要获取用户定义的转换方法的目标类型。</param>
        /// <returns>如果存在从源类型到目标类型的用户定义的显式转换方法,则返回该方法;
        /// 否则返回 <c>null</c>。</returns>
        public static ConversionMethod GetExplicitConversion(Type sourceType, Type targetType)
        {
            Type exactSource = null, exactTarget = null;
            UniqueValue <ConversionMethod> method = new UniqueValue <ConversionMethod>();
            Conversion conv = GetTypeConversions(sourceType.GetNonNullableType());

            for (int i = conv.ConvertToIndex; i < conv.Methods.Length; i++)
            {
                ConversionMethod m = conv.Methods[i];
                if (targetType.IsStandardExplicitFrom(m.TargetType))
                {
                    GetBestConversion(m, ref exactSource, ref exactTarget, method);
                }
            }
            conv = GetTypeConversions(targetType.GetNonNullableType());
            for (int i = Conversion.ConvertFromIndex; i < conv.ConvertToIndex; i++)
            {
                ConversionMethod m = conv.Methods[i];
                if (m.SourceType.IsStandardExplicitFrom(sourceType))
                {
                    GetBestConversion(m, ref exactSource, ref exactTarget, method);
                }
            }
            if (method.IsUnique)
            {
                return(method.Value);
            }
            return(null);
        }
Exemple #4
0
		/// <summary>
		/// 返回指定类型的对象,其值等效于指定对象。参数提供区域性特定的格式设置信息。
		/// 支持可空类型、枚举和用户自定义类型转换。
		/// </summary>
		/// <param name="value">要转换的对象。</param>
		/// <param name="conversionType">要返回的对象的类型。</param>
		/// <param name="provider">一个提供区域性特定的格式设置信息的对象。</param>
		/// <returns>一个对象,其类型为 <paramref name="conversionType"/>,
		/// 并且其值等效于 <paramref name="value"/>。</returns>
		/// <overloads>
		/// <summary>
		/// 返回指定类型的对象,其值等效于指定对象。支持可空类型、枚举和用户自定义类型转换。
		/// </summary>
		/// </overloads>
		public static object ChangeType(object value, Type conversionType, IFormatProvider provider)
		{
			Type nonNullableType;
			if (BasicChangeType(ref value, conversionType, out nonNullableType))
			{
				return value;
			}
			Type type = value.GetType();
			// 尝试显示枚举转换。
			if (conversionType.IsEnumExplicitFrom(type))
			{
				if (conversionType.IsEnum)
				{
					// Enum.ToObject 不支持 char, float, double 和 decimal。
					switch (Type.GetTypeCode(type))
					{
						case TypeCode.Char:
							value = (ushort)(char)value;
							break;
						case TypeCode.Single:
							value = (long)(float)value;
							break;
						case TypeCode.Double:
							value = (long)(double)value;
							break;
						case TypeCode.Decimal:
							value = (long)(decimal)value;
							break;
					}
					return Enum.ToObject(conversionType, value);
				}
				return Convert.ChangeType(value, conversionType, provider);
			}
			// 尝试标准显式类型转换。
			bool success;
			object result = StandardExplicitChangeType(value, type, nonNullableType, provider, out success);
			if (success)
			{
				return result;
			}
			// 对显式类型转换运算符进行判断。
			ConversionMethod method = ConversionCache.GetExplicitConversion(type, conversionType);
			if (method != null)
			{
				value = MethodBase.GetMethodFromHandle(method.Method).Invoke(null, new [] { value });
				if (value != null)
				{
					type = value.GetType();
					if (type != nonNullableType)
					{
						// 处理用户定义显式类型转换之后的标准显式类型转换。
						value = StandardExplicitChangeType(value, type, nonNullableType, provider, out success);
					}
				}
				return value;
			}
			// 尝试其他支持的转换。
			return Convert.ChangeType(value, conversionType, provider);
		}
Exemple #5
0
        /// <summary>
        /// 根据给定的用户定义转换获取最合适的转换。
        /// </summary>
        /// <param name="method">要测试的用户定义转换。</param>
        /// <param name="exactSource">当前最合适的源类型。</param>
        /// <param name="exactTarget">当前最合适的目标类型。</param>
        /// <param name="uniqueMethod">最合适的转换。</param>
        private static void GetBestConversion(ConversionMethod method, ref Type exactSource, ref Type exactTarget,
			UniqueValue<ConversionMethod> uniqueMethod)
        {
            if (exactSource != method.SourceType)
            {
                if (exactSource != null && method.SourceType.IsAssignableFrom(exactSource))
                {
                    return;
                }
                else
                {
                    exactSource = method.SourceType;
                    uniqueMethod.Reset();
                }
            }
            if (exactTarget != method.TargetType)
            {
                if (exactTarget != null && exactTarget.IsAssignableFrom(method.TargetType))
                {
                    return;
                }
                else
                {
                    exactTarget = method.TargetType;
                    uniqueMethod.Reset();
                }
            }
            uniqueMethod.Value = method;
        }
Exemple #6
0
        /// <summary>
        /// 返回指定类型中用户定义的转换方法。
        /// </summary>
        /// <param name="type">要获取类型转换方法的类型。</param>
        /// <returns>指定类型中用户定义的转换方法。</returns>
        private static Conversion GetTypeConversions(Type type)
        {
            TypeCode typeCode = Type.GetTypeCode(type);

            if (typeCode != TypeCode.Object && typeCode != TypeCode.Decimal)
            {
                // 其余内置类型都不包含类型转换运算符。
                return(Conversion.Empty);
            }
            return(Conversions.GetOrAdd(type, t =>
            {
                Conversion conv = new Conversion();
                List <ConversionMethod> cList = new List <ConversionMethod>();
                MethodInfo[] methods = t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
                for (int i = 0; i < methods.Length; i++)
                {
                    MethodInfo m = methods[i];
                    bool opImplicit = m.Name.Equals(ImplicitConversionName, StringComparison.Ordinal);
                    // 如果 opImplicit 已经为 true,则不需要再次进行方法名称的比较。
                    bool opExplicit = opImplicit ? false : m.Name.Equals(ExplicitConviersionName, StringComparison.Ordinal);
                    if (opImplicit || opExplicit)
                    {
                        if (m.ReturnType == type)
                        {
                            // 转换自其它类型。
                            int index = conv.ImplicitConvertFromIndex;
                            if (opExplicit)
                            {
                                index = Conversion.ConvertFromIndex;
                                conv.ImplicitConvertFromIndex++;
                            }
                            conv.ConvertToIndex++;
                            conv.ImplicitConvertToIndex++;
                            cList.Insert(index, new ConversionMethod(m.GetParameters()[0].ParameterType, t, m));
                        }
                        else
                        {
                            // 转换到其它类型。
                            int index = conv.ImplicitConvertToIndex;
                            if (opExplicit)
                            {
                                index = conv.ConvertToIndex;
                                conv.ImplicitConvertToIndex++;
                            }
                            cList.Insert(index, new ConversionMethod(t, m.ReturnType, m));
                        }
                    }
                }
                // 如果子类的类型转换运算符与基类完全相同,则为 true;否则为 false。
                bool sameWithBase = (cList.Count == 0);
                // 基类转换为其它类型的运算符是可以由子类继承的。
                if (type.IsClass)
                {
                    Conversion baseConv = GetTypeConversions(type.BaseType);
                    for (int i = baseConv.ConvertToIndex; i < baseConv.Methods.Length; i++)
                    {
                        ConversionMethod m = baseConv.Methods[i];
                        bool contains = false;
                        for (int j = conv.ConvertToIndex; j < cList.Count; j++)
                        {
                            if (cList[j].TargetType == m.TargetType)
                            {
                                sameWithBase = false;
                                contains = true;
                                break;
                            }
                        }
                        if (!contains)
                        {
                            if (i >= baseConv.ImplicitConvertToIndex)
                            {
                                cList.Insert(conv.ImplicitConvertToIndex, m);
                            }
                            else
                            {
                                cList.Insert(conv.ConvertToIndex, m);
                                conv.ImplicitConvertToIndex++;
                            }
                        }
                    }
                    if (sameWithBase)
                    {
                        // 这时候可以略微节约内存。
                        return baseConv;
                    }
                }
                if (sameWithBase)
                {
                    // 这时候可以略微节约内存。
                    return Conversion.Empty;
                }
                conv.Methods = cList.ToArray();
                return conv;
            }));
        }