/// <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); }
/// <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); }
/// <summary> /// 确定当前的 <see cref="System.Type"/> 的实例是否可以从指定 <see cref="System.Type"/> /// 的实例进行隐式类型转换。 /// </summary> /// <param name="type">要判断的实例。</param> /// <param name="fromType">要与当前类型进行比较的类型。</param> /// <returns>如果当前 <see cref="System.Type"/> 可以从 <paramref name="fromType"/> /// 的实例分配或进行隐式类型转换,则为 <c>true</c>;否则为 <c>false</c>。</returns> /// <remarks> /// 判断类型间能否进行隐式类型转换的算法来自于 《CSharp Language Specification》v5.0 /// 的第 6.1 节,更多信息可以参考我的博客文章 /// <see href="http://www.cnblogs.com/cyjb/archive/p/TypeAssignableFrom.html"> /// 《C# 判断类型间能否隐式或强制类型转换,以及开放泛型类型转换》</see>。</remarks> /// <example> /// 下面是 <see cref="IsImplicitFrom"/> 方法与 <see cref="System.Type.IsAssignableFrom"/> 方法的一些对比。 /// <code> /// Console.WriteLine(typeof(object).IsAssignableFrom(typeof(uint))); // True /// Console.WriteLine(typeof(object).IsImplicitFrom(typeof(uint))); // True /// Console.WriteLine(typeof(int).IsAssignableFrom(typeof(short))); // False /// Console.WriteLine(typeof(int).IsImplicitFrom(typeof(short))); // True /// Console.WriteLine(typeof(long?).IsAssignableFrom(typeof(int?))); // False /// Console.WriteLine(typeof(long?).IsImplicitFrom(typeof(int?))); // True /// Console.WriteLine(typeof(long).IsAssignableFrom(typeof(TestClass))); // False /// Console.WriteLine(typeof(long).IsImplicitFrom(typeof(TestClass))); // True /// class TestClass { /// public static implicit operator int(TestClass t) { return 1; } /// } /// </code> /// </example> /// <seealso href="http://www.cnblogs.com/cyjb/archive/p/TypeAssignableFrom.html"> /// 《C# 判断类型间能否隐式或强制类型转换,以及开放泛型类型转换》</seealso> public static bool IsImplicitFrom(this Type type, Type fromType) { if (type == null || fromType == null) { return(false); } // 标识转换。 if (type == fromType) { return(true); } // 对引用类型的支持。 if (type.IsByRef) { type = type.GetElementType(); } if (fromType.IsByRef) { fromType = type.GetElementType(); } // 总是可以隐式类型转换为 Object。 if (type.Equals(typeof(object))) { return(true); } // 判断是否可以进行标准隐式转换。 if (IsStandardImplicitFrom(type, fromType)) { return(true); } // 对隐式类型转换运算符进行判断。 // 处理提升转换运算符。 Type nonNullalbeType, nonNullableFromType; if (IsNullableType(type, out nonNullalbeType) && IsNullableType(fromType, out nonNullableFromType)) { type = nonNullalbeType; fromType = nonNullableFromType; } return(ConversionCache.GetImplicitConversion(fromType, type) != null); }
/// <summary> /// 确定当前的 <see cref="System.Type"/> 的实例是否可以从指定 <see cref="System.Type"/> /// 的实例进行强制类型转换。 /// </summary> /// <param name="type">要判断的实例。</param> /// <param name="fromType">要与当前类型进行比较的类型。</param> /// <returns>如果当前 <see cref="System.Type"/> 可以从 <paramref name="fromType"/> /// 的实例分配或进行强制类型转换,则为 <c>true</c>;否则为 <c>false</c>。</returns> /// <remarks> /// 判断类型间能否进行显式类型转换的算法来自于 《CSharp Language Specification》v5.0 /// 的第 6.2 节,更多信息可以参考我的博客文章 /// <see href="http://www.cnblogs.com/cyjb/archive/p/TypeAssignableFrom.html"> /// 《C# 判断类型间能否隐式或强制类型转换,以及开放泛型类型转换》</see>。</remarks> /// <example> /// 下面是 <see cref="IsImplicitFrom"/> 方法的一些实例。 /// <code> /// Console.WriteLine(typeof(uint).IsExplicitFrom(typeof(object))); // True /// Console.WriteLine(typeof(short).IsExplicitFrom(typeof(int))); // True /// Console.WriteLine(typeof(int).IsExplicitFrom(typeof(long?))); // True /// Console.WriteLine(typeof(long).IsExplicitFrom(typeof(TestClass))); // True /// class TestClass { /// public static explicit operator int(TestClass t) { return 1; } /// } /// </code> /// </example> /// <seealso href="http://www.cnblogs.com/cyjb/archive/p/TypeAssignableFrom.html"> /// 《C# 判断类型间能否隐式或强制类型转换,以及开放泛型类型转换》</seealso> public static bool IsExplicitFrom(this Type type, Type fromType) { if (type == null || fromType == null) { return(false); } // 标识转换。 if (type == fromType) { return(true); } // 对引用类型的支持。 if (type.IsByRef) { type = type.GetElementType(); } if (fromType.IsByRef) { fromType = type.GetElementType(); } // 总是可以与 Object 进行显示类型转换。 if (type.Equals(typeof(object)) || fromType.Equals(typeof(object))) { return(true); } // 对 Nullable<T> 的支持。 IsNullableType(ref type); IsNullableType(ref fromType); // 显式枚举转换。 if (type.IsEnumExplicitFrom(fromType)) { return(true); } // 判断是否可以进行标准显式转换。 if (IsStandardExplicitFrom(type, fromType)) { return(true); } // 对显式类型转换运算符进行判断。 return(ConversionCache.GetExplicitConversion(fromType, type) != null); }