IConvertibleExtensions.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. using System;
  2. using System.ComponentModel;
  3. using System.Globalization;
  4. using System.Linq;
  5. namespace Masuit.Tools;
  6. public static class IConvertibleExtensions
  7. {
  8. public static bool IsNumeric(this Type type)
  9. {
  10. switch (Type.GetTypeCode(type))
  11. {
  12. case TypeCode.Byte:
  13. case TypeCode.SByte:
  14. case TypeCode.UInt16:
  15. case TypeCode.UInt32:
  16. case TypeCode.UInt64:
  17. case TypeCode.Int16:
  18. case TypeCode.Int32:
  19. case TypeCode.Int64:
  20. case TypeCode.Decimal:
  21. case TypeCode.Double:
  22. case TypeCode.Single:
  23. return true;
  24. default:
  25. return false;
  26. }
  27. }
  28. /// <summary>
  29. /// 类型直转
  30. /// </summary>
  31. /// <typeparam name="T"></typeparam>
  32. /// <param name="value"></param>
  33. /// <returns></returns>
  34. public static T ConvertTo<T>(this IConvertible value) where T : IConvertible
  35. {
  36. if (value != null)
  37. {
  38. var type = typeof(T);
  39. if (value.GetType() == type)
  40. {
  41. return (T)value;
  42. }
  43. if (type.IsNumeric())
  44. {
  45. return (T)value.ToType(type, new NumberFormatInfo());
  46. }
  47. if (value == DBNull.Value)
  48. {
  49. return default;
  50. }
  51. if (type.IsEnum)
  52. {
  53. return (T)Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
  54. }
  55. if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
  56. {
  57. var underlyingType = Nullable.GetUnderlyingType(type);
  58. return (T)(underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType));
  59. }
  60. var converter = TypeDescriptor.GetConverter(value);
  61. if (converter.CanConvertTo(type))
  62. {
  63. return (T)converter.ConvertTo(value, type);
  64. }
  65. converter = TypeDescriptor.GetConverter(type);
  66. if (converter.CanConvertFrom(value.GetType()))
  67. {
  68. return (T)converter.ConvertFrom(value);
  69. }
  70. return (T)Convert.ChangeType(value, type);
  71. }
  72. return (T)value;
  73. }
  74. /// <summary>
  75. /// 类型直转
  76. /// </summary>
  77. /// <typeparam name="T"></typeparam>
  78. /// <param name="value"></param>
  79. /// <param name="defaultValue">转换失败的默认值</param>
  80. /// <returns></returns>
  81. public static T TryConvertTo<T>(this IConvertible value, T defaultValue = default) where T : IConvertible
  82. {
  83. try
  84. {
  85. return ConvertTo<T>(value);
  86. }
  87. catch
  88. {
  89. return defaultValue;
  90. }
  91. }
  92. /// <summary>
  93. /// 类型直转
  94. /// </summary>
  95. /// <typeparam name="T"></typeparam>
  96. /// <param name="value"></param>
  97. /// <param name="result">转换失败的默认值</param>
  98. /// <returns></returns>
  99. public static bool TryConvertTo<T>(this IConvertible value, out T result) where T : IConvertible
  100. {
  101. try
  102. {
  103. result = ConvertTo<T>(value);
  104. return true;
  105. }
  106. catch
  107. {
  108. result = default;
  109. return false;
  110. }
  111. }
  112. /// <summary>
  113. /// 类型直转
  114. /// </summary>
  115. /// <param name="value"></param>
  116. /// <param name="type">目标类型</param>
  117. /// <param name="result">转换失败的默认值</param>
  118. /// <returns></returns>
  119. public static bool TryConvertTo(this IConvertible value, Type type, out object result)
  120. {
  121. try
  122. {
  123. result = ConvertTo(value, type);
  124. return true;
  125. }
  126. catch
  127. {
  128. result = default;
  129. return false;
  130. }
  131. }
  132. /// <summary>
  133. /// 类型直转
  134. /// </summary>
  135. /// <param name="value"></param>
  136. /// <param name="type">目标类型</param>
  137. /// <returns></returns>
  138. public static object ConvertTo(this IConvertible value, Type type)
  139. {
  140. if (value == null)
  141. {
  142. return default;
  143. }
  144. if (value.GetType() == type)
  145. {
  146. return value;
  147. }
  148. if (value == DBNull.Value)
  149. {
  150. return null;
  151. }
  152. if (type.IsAssignableFrom(typeof(string)))
  153. {
  154. return value.ToString();
  155. }
  156. if (type.IsEnum)
  157. {
  158. return Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
  159. }
  160. if (type.IsAssignableFrom(typeof(Guid)))
  161. {
  162. return Guid.Parse(value.ToString());
  163. }
  164. if (type.IsAssignableFrom(typeof(DateTime)))
  165. {
  166. return DateTime.Parse(value.ToString());
  167. }
  168. if (type.IsAssignableFrom(typeof(DateTimeOffset)))
  169. {
  170. return DateTimeOffset.Parse(value.ToString());
  171. }
  172. if (type.IsNumeric())
  173. {
  174. return value.ToType(type, new NumberFormatInfo());
  175. }
  176. if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
  177. {
  178. var underlyingType = Nullable.GetUnderlyingType(type);
  179. return underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType);
  180. }
  181. var converter = TypeDescriptor.GetConverter(value);
  182. if (converter.CanConvertTo(type))
  183. {
  184. return converter.ConvertTo(value, type);
  185. }
  186. converter = TypeDescriptor.GetConverter(type);
  187. return converter.CanConvertFrom(value.GetType()) ? converter.ConvertFrom(value) : Convert.ChangeType(value, type);
  188. }
  189. /// <summary>
  190. /// 对象类型转换
  191. /// </summary>
  192. /// <param name="this">当前值</param>
  193. /// <returns>转换后的对象</returns>
  194. public static T ChangeTypeTo<T>(this object @this)
  195. {
  196. return (T)ChangeType(@this, typeof(T));
  197. }
  198. /// <summary>
  199. /// 对象类型转换
  200. /// </summary>
  201. /// <param name="this">当前值</param>
  202. /// <param name="type">指定类型的类型</param>
  203. /// <returns>转换后的对象</returns>
  204. public static object ChangeType(this object @this, Type type)
  205. {
  206. var currType = Nullable.GetUnderlyingType(@this.GetType()) ?? @this.GetType();
  207. type = Nullable.GetUnderlyingType(type) ?? type;
  208. if (@this == DBNull.Value)
  209. {
  210. if (!type.IsValueType)
  211. {
  212. return null;
  213. }
  214. throw new Exception("不能将null值转换为" + type.Name + "类型!");
  215. }
  216. if (currType == type)
  217. {
  218. return @this;
  219. }
  220. if (type.IsAssignableFrom(typeof(string)))
  221. {
  222. return @this.ToString();
  223. }
  224. if (type.IsEnum)
  225. {
  226. return Enum.Parse(type, @this.ToString(), true);
  227. }
  228. if (type.IsAssignableFrom(typeof(Guid)))
  229. {
  230. return Guid.Parse(@this.ToString());
  231. }
  232. if (!type.IsArray || !currType.IsArray)
  233. {
  234. return Convert.ChangeType(@this, type);
  235. }
  236. var length = ((Array)@this).Length;
  237. var targetType = Type.GetType(type.FullName.Trim('[', ']'));
  238. var array = Array.CreateInstance(targetType, length);
  239. for (int j = 0; j < length; j++)
  240. {
  241. var tmp = ((Array)@this).GetValue(j);
  242. array.SetValue(ChangeType(tmp, targetType), j);
  243. }
  244. return array;
  245. }
  246. }