IConvertibleExtensions.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. using System;
  2. using System.ComponentModel;
  3. using System.Globalization;
  4. namespace Masuit.Tools;
  5. public static class IConvertibleExtensions
  6. {
  7. public static bool IsNumeric(this Type type)
  8. {
  9. switch (Type.GetTypeCode(type))
  10. {
  11. case TypeCode.Byte:
  12. case TypeCode.SByte:
  13. case TypeCode.UInt16:
  14. case TypeCode.UInt32:
  15. case TypeCode.UInt64:
  16. case TypeCode.Int16:
  17. case TypeCode.Int32:
  18. case TypeCode.Int64:
  19. case TypeCode.Decimal:
  20. case TypeCode.Double:
  21. case TypeCode.Single:
  22. return true;
  23. default:
  24. return false;
  25. }
  26. }
  27. /// <summary>
  28. /// 类型直转
  29. /// </summary>
  30. /// <typeparam name="T"></typeparam>
  31. /// <param name="value"></param>
  32. /// <returns></returns>
  33. public static T ConvertTo<T>(this IConvertible value) where T : IConvertible
  34. {
  35. if (value != null)
  36. {
  37. var type = typeof(T);
  38. if (value.GetType() == type)
  39. {
  40. return (T)value;
  41. }
  42. if (type.IsNumeric())
  43. {
  44. return (T)value.ToType(type, new NumberFormatInfo());
  45. }
  46. if (value == DBNull.Value)
  47. {
  48. return default;
  49. }
  50. if (type.IsEnum)
  51. {
  52. return (T)Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
  53. }
  54. if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
  55. {
  56. var underlyingType = Nullable.GetUnderlyingType(type);
  57. return (T)(underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType));
  58. }
  59. TypeConverter converter = TypeDescriptor.GetConverter(value);
  60. if (converter != null)
  61. {
  62. if (converter.CanConvertTo(type))
  63. {
  64. return (T)converter.ConvertTo(value, type);
  65. }
  66. }
  67. converter = TypeDescriptor.GetConverter(type);
  68. if (converter != null)
  69. {
  70. if (converter.CanConvertFrom(value.GetType()))
  71. {
  72. return (T)converter.ConvertFrom(value);
  73. }
  74. }
  75. return (T)Convert.ChangeType(value, type);
  76. }
  77. return (T)value;
  78. }
  79. /// <summary>
  80. /// 类型直转
  81. /// </summary>
  82. /// <typeparam name="T"></typeparam>
  83. /// <param name="value"></param>
  84. /// <param name="defaultValue">转换失败的默认值</param>
  85. /// <returns></returns>
  86. public static T TryConvertTo<T>(this IConvertible value, T defaultValue = default) where T : IConvertible
  87. {
  88. try
  89. {
  90. return ConvertTo<T>(value);
  91. }
  92. catch
  93. {
  94. return defaultValue;
  95. }
  96. }
  97. /// <summary>
  98. /// 类型直转
  99. /// </summary>
  100. /// <typeparam name="T"></typeparam>
  101. /// <param name="value"></param>
  102. /// <param name="result">转换失败的默认值</param>
  103. /// <returns></returns>
  104. public static bool TryConvertTo<T>(this IConvertible value, out T result) where T : IConvertible
  105. {
  106. try
  107. {
  108. result = ConvertTo<T>(value);
  109. return true;
  110. }
  111. catch
  112. {
  113. result = default;
  114. return false;
  115. }
  116. }
  117. /// <summary>
  118. /// 类型直转
  119. /// </summary>
  120. /// <param name="value"></param>
  121. /// <param name="type">目标类型</param>
  122. /// <param name="result">转换失败的默认值</param>
  123. /// <returns></returns>
  124. public static bool TryConvertTo(this IConvertible value, Type type, out object result)
  125. {
  126. try
  127. {
  128. result = ConvertTo(value, type);
  129. return true;
  130. }
  131. catch
  132. {
  133. result = default;
  134. return false;
  135. }
  136. }
  137. /// <summary>
  138. /// 类型直转
  139. /// </summary>
  140. /// <param name="value"></param>
  141. /// <param name="type">目标类型</param>
  142. /// <returns></returns>
  143. public static object ConvertTo(this IConvertible value, Type type)
  144. {
  145. if (value == null)
  146. {
  147. return default;
  148. }
  149. if (value.GetType() == type)
  150. {
  151. return value;
  152. }
  153. if (value == DBNull.Value)
  154. {
  155. return null;
  156. }
  157. if (type.IsEnum)
  158. {
  159. return Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
  160. }
  161. if (type.IsNumeric())
  162. {
  163. return value.ToType(type, new NumberFormatInfo());
  164. }
  165. if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
  166. {
  167. var underlyingType = Nullable.GetUnderlyingType(type);
  168. return underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType);
  169. }
  170. var converter = TypeDescriptor.GetConverter(value);
  171. if (converter != null)
  172. {
  173. if (converter.CanConvertTo(type))
  174. {
  175. return converter.ConvertTo(value, type);
  176. }
  177. }
  178. converter = TypeDescriptor.GetConverter(type);
  179. if (converter != null)
  180. {
  181. if (converter.CanConvertFrom(value.GetType()))
  182. {
  183. return converter.ConvertFrom(value);
  184. }
  185. }
  186. return Convert.ChangeType(value, type);
  187. }
  188. }