TypeExtension.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. using Newtonsoft.Json;
  2. using SqlSugar;
  3. using System.Collections.Concurrent;
  4. using System.ComponentModel;
  5. using System.Data;
  6. using System.Globalization;
  7. using System.Numerics;
  8. using System.Reflection;
  9. using System.Security.Cryptography;
  10. using System.Text;
  11. using System.Text.RegularExpressions;
  12. namespace ServiceCenter.Extensions
  13. {
  14. /// <summary>
  15. /// 类型转换扩展
  16. /// </summary>
  17. public static class TypeExtension
  18. {
  19. /// <summary>
  20. /// 将字符串转换为short
  21. /// </summary>
  22. /// <param name="value">需要转换的字符串</param>
  23. /// <returns></returns>
  24. public static short ToShort(this string value)
  25. {
  26. return Convert.ToInt16(value);
  27. }
  28. /// <summary>
  29. /// 将int转换为short
  30. /// </summary>
  31. /// <param name="value">需要转换的字符串</param>
  32. /// <returns></returns>
  33. public static short ToShort(this int value)
  34. {
  35. return Convert.ToInt16(value);
  36. }
  37. /// <summary>
  38. /// 将decimal转换为short
  39. /// </summary>
  40. /// <param name="value">需要转换的字符串</param>
  41. /// <returns></returns>
  42. public static short ToShort(this decimal value)
  43. {
  44. return Convert.ToInt16(value);
  45. }
  46. /// <summary>
  47. /// 将字符串转换为int
  48. /// </summary>
  49. /// <param name="value">需要转换的字符串</param>
  50. /// <returns></returns>
  51. public static int ToInt(this string value)
  52. {
  53. return Convert.ToInt32(value);
  54. }
  55. /// <summary>
  56. /// 将字符串转换为long
  57. /// </summary>
  58. /// <param name="value">需要转换的字符串</param>
  59. /// <returns></returns>
  60. public static long ToLong(this string value)
  61. {
  62. return Convert.ToInt64(value);
  63. }
  64. /// <summary>
  65. /// 获取最后一位数字
  66. /// </summary>
  67. /// <param name="value">字符串</param>
  68. /// <returns></returns>
  69. public static int GetLastDigit(this string value)
  70. {
  71. return Convert.ToInt32(Regex.Match(value, @"\d+$").Value);
  72. }
  73. /// <summary>
  74. /// 判断值为奇数/偶数
  75. /// </summary>
  76. /// <param name="value">需要判断的值</param>
  77. /// <returns> true:是奇数 false:是偶数</returns>
  78. public static bool OddNumberOrEven(this short value)
  79. {
  80. return value % 2 != 0;
  81. }
  82. /// <summary>
  83. /// 获取short类型Code,只限设备组
  84. /// </summary>
  85. /// <param name="value"></param>
  86. /// <returns></returns>
  87. public static short GetShortCode(this string value)
  88. {
  89. return value.Replace("G", "").ToShort();
  90. }
  91. /// <summary>
  92. /// 扩展方法,获得枚举的Description
  93. /// </summary>
  94. /// <param name="value">枚举值</param>
  95. /// <param name="nameInstead">当枚举值没有定义DescriptionAttribute,是否使用枚举名代替,默认是使用</param>
  96. /// <returns>枚举的Description</returns>
  97. public static string GetDescription(this Enum value, Boolean nameInstead = true)
  98. {
  99. Type type = value.GetType();
  100. string name = Enum.GetName(type, value);
  101. if (name == null)
  102. {
  103. return null;
  104. }
  105. FieldInfo field = type.GetField(name);
  106. DescriptionAttribute attribute = System.Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
  107. if (attribute == null && nameInstead == true)
  108. {
  109. return name;
  110. }
  111. return attribute?.Description;
  112. }
  113. /// <summary>
  114. /// 获取属性的描述信息
  115. /// </summary>
  116. public static string GetDescription(this Type type, string proName)
  117. {
  118. PropertyInfo pro = type.GetProperty(proName);
  119. string des = proName;
  120. if (pro != null)
  121. {
  122. des = pro.GetDescription();
  123. }
  124. return des;
  125. }
  126. public static string JsonToString(this object value)
  127. {
  128. return JsonConvert.SerializeObject(value);
  129. }
  130. /// <summary>
  131. /// 获取属性的描述信息
  132. /// </summary>
  133. public static string GetDescription(this MemberInfo info)
  134. {
  135. var attrs = (DescriptionAttribute[])info.GetCustomAttributes(typeof(DescriptionAttribute), false);
  136. string des = info.Name;
  137. foreach (DescriptionAttribute attr in attrs)
  138. {
  139. des = attr.Description;
  140. }
  141. return des;
  142. }
  143. /// <summary>
  144. /// 数据映射
  145. /// </summary>
  146. /// <typeparam name="D">映射目标实体Type</typeparam>
  147. /// <typeparam name="S"></typeparam>
  148. /// <param name="s"></param>
  149. /// <returns></returns>
  150. public static D Mapper<D, S>(this S s)
  151. {
  152. var d = Activator.CreateInstance<D>();
  153. var sType = s?.GetType();
  154. var dType = typeof(D);
  155. foreach (var sP in sType.GetProperties())
  156. {
  157. foreach (var dP in dType.GetProperties())
  158. {
  159. if (dP.Name == sP.Name)
  160. {
  161. dP.SetValue(d, sP.GetValue(s));
  162. break;
  163. }
  164. }
  165. }
  166. return d;
  167. }
  168. public static object Copy(this object obj, object type)
  169. {
  170. foreach (var p in type.GetType().GetProperties())
  171. {
  172. var p2 = obj.GetType().GetProperty(p.Name);
  173. if (p2 != null && p2.PropertyType == p.PropertyType)
  174. {
  175. var a = p2.GetValue(obj);
  176. p.SetValue(type, p2.GetValue(obj));
  177. }
  178. }
  179. return type;
  180. }
  181. public static object Copy(this object obj, Type type)
  182. {
  183. var res = Activator.CreateInstance(type);
  184. foreach (var p in type.GetProperties())
  185. {
  186. var p2 = obj.GetType().GetProperty(p.Name);
  187. if (p2 != null)
  188. {
  189. var value = p2.GetValue(obj);
  190. p.SetValue(res, value);
  191. }
  192. }
  193. return res;
  194. }
  195. //public static object Copy(this object source, Type t)
  196. //{
  197. // var obj = Activator.CreateInstance(t);
  198. // foreach (var p in t.GetProperties())
  199. // {
  200. // var p2 = source.GetType().GetProperty(p.Name);
  201. // var value = p2.GetValue(source);
  202. // p.SetValue(obj, value);
  203. // }
  204. // return obj;
  205. //}
  206. /// <summary>
  207. /// 获取字典
  208. /// </summary>
  209. /// <typeparam name="T1"></typeparam>
  210. /// <typeparam name="T2"></typeparam>
  211. /// <typeparam name="T3"></typeparam>
  212. /// <param name="t3"></param>
  213. /// <returns></returns>
  214. public static Dictionary<string, object> EntityClassToDictionary<T>(T t)
  215. {
  216. var type = typeof(SugarColumn);
  217. Dictionary<string, object> d = new Dictionary<string, object>();
  218. var sType = t.GetType();
  219. foreach (var sP in sType.GetProperties())
  220. {
  221. if (sP.CustomAttributes.Any(v => v.AttributeType == type) && sP.Name != "VER" && sP.Name != "ID")
  222. {
  223. d.Add(sP.Name, sP.GetValue(t));
  224. }
  225. }
  226. return d;
  227. }
  228. /// <summary>
  229. /// 获取MD5字符串
  230. /// </summary>
  231. /// <param name="myString"></param>
  232. /// <returns></returns>
  233. public static string GetMD5(this string myString)
  234. {
  235. var md5 = MD5.Create();
  236. var fromData = Encoding.Unicode.GetBytes(myString);
  237. var targetData = md5.ComputeHash(fromData);
  238. string byte2String = null;
  239. for (var i = 0; i < targetData.Length; i++)
  240. {
  241. byte2String += targetData[i].ToString("x");
  242. }
  243. return byte2String;
  244. }
  245. /// <summary>
  246. /// DataTable转换成实体类
  247. /// </summary>
  248. /// <typeparam name="T"></typeparam>
  249. /// <param name="dt"></param>
  250. /// <returns></returns>
  251. public static List<object> TableToEntity(this DataTable dt, string typeName)
  252. {
  253. var list = new List<object>();
  254. try
  255. {
  256. foreach (DataRow row in dt.Rows)
  257. {
  258. var entity = Type.GetType(typeName);
  259. PropertyInfo[] pArray = entity.GetType().GetProperties();
  260. foreach (var p in pArray)
  261. {
  262. if (dt.Columns.Contains(p.Name))
  263. {
  264. if (!p.CanWrite) continue;
  265. var value = row[p.Name];
  266. if (value != DBNull.Value)
  267. {
  268. var targetType = p.PropertyType;
  269. var convertType = targetType;
  270. if (targetType.IsGenericType && targetType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
  271. {
  272. //可空类型
  273. var nullableConverter = new NullableConverter(targetType);
  274. convertType = nullableConverter.UnderlyingType;
  275. }
  276. if (!string.IsNullOrEmpty(convertType.FullName) && !string.IsNullOrEmpty(value.ToString()))
  277. {
  278. value = Convert.ChangeType(value, convertType);
  279. }
  280. switch (convertType.FullName)
  281. {
  282. case "System.Decimal":
  283. p.SetValue(entity, Convert.ToDecimal(value), null);
  284. break;
  285. case "System.String":
  286. p.SetValue(entity, Convert.ToString(value), null);
  287. break;
  288. case "System.Int32":
  289. p.SetValue(entity, Convert.ToInt32(value), null);
  290. break;
  291. case "System.Int64":
  292. p.SetValue(entity, Convert.ToInt64(value), null);
  293. break;
  294. case "System.Int16":
  295. p.SetValue(entity, Convert.ToInt16(value), null);
  296. break;
  297. case "System.Double":
  298. p.SetValue(entity, Convert.ToDouble(value), null);
  299. break;
  300. case "System.Single":
  301. p.SetValue(entity, Convert.ToSingle(value), null);
  302. break;
  303. case "System.DateTime":
  304. p.SetValue(entity, Convert.ToDateTime(value), null);
  305. break;
  306. default:
  307. p.SetValue(entity, value, null);
  308. break;
  309. }
  310. }
  311. }
  312. }
  313. list.Add(entity);
  314. }
  315. }
  316. catch (Exception ex)
  317. {
  318. }
  319. return list;
  320. }
  321. /// <summary>
  322. /// 转换到目标类型
  323. /// </summary>
  324. /// <param name="value"></param>
  325. /// <typeparam name="T"></typeparam>
  326. /// <returns></returns>
  327. internal static T ConvertTo<T>(this object value) => (T)typeof(T).FromObject(value);
  328. public static string yyyy(this DateTime time)
  329. {
  330. return time.GetFormat(GetFormatterEnum.yyyy);
  331. }
  332. public static string yyyyMM(this DateTime time)
  333. {
  334. return time.GetFormat(GetFormatterEnum.yyyyMM);
  335. }
  336. public static string yyyyMMdd(this DateTime time)
  337. {
  338. return time.GetFormat(GetFormatterEnum.yyyyMMdd);
  339. }
  340. public static string yyyyMMddhh(this DateTime time)
  341. {
  342. return time.GetFormat(GetFormatterEnum.yyyyMMddhh);
  343. }
  344. public static string yyyyMMddhhmm(this DateTime time)
  345. {
  346. return time.GetFormat(GetFormatterEnum.yyyyMMddhhmm);
  347. }
  348. public static string yyyyMMddhhmmss(this DateTime time)
  349. {
  350. return time.GetFormat(GetFormatterEnum.yyyyMMddhhmmss);
  351. }
  352. public static string yyyyMMddhhmmssf(this DateTime time)
  353. {
  354. return time.GetFormat(GetFormatterEnum.yyyyMMddhhmmssfffffff);
  355. }
  356. /// <summary>
  357. /// 获取指定格式时间的字符串
  358. /// </summary>
  359. /// <param name="time">时间</param>
  360. /// <param name="formatterEnum">类型</param>
  361. /// <returns></returns>
  362. public static string GetFormat(this DateTime time, GetFormatterEnum formatterEnum)
  363. {
  364. switch (formatterEnum)
  365. {
  366. case GetFormatterEnum.Default:
  367. return time.ToString();
  368. case GetFormatterEnum.yyyy:
  369. return time.ToString("yyyy");
  370. case GetFormatterEnum.yyyyMM:
  371. return time.ToString("yyyy-MM");
  372. case GetFormatterEnum.yyyyMMdd:
  373. return time.ToString("yyyy-MM-dd");
  374. case GetFormatterEnum.yyyyMMddhh:
  375. return time.ToString("yyyy-MM-dd HH");
  376. case GetFormatterEnum.yyyyMMddhhmm:
  377. return time.ToString("yyyy-MM-dd HH:mm");
  378. case GetFormatterEnum.yyyyMMddhhmmss:
  379. return time.ToString("yyyy-MM-dd HH:mm:ss");
  380. case GetFormatterEnum.yyyyMMddhhmmssfffffff:
  381. return time.ToString("yyyy-MM-dd HH:mm:ss:fffffff");
  382. case GetFormatterEnum.only:
  383. return time.ToString("yyyyMMddHHmmssfffffff");
  384. default:
  385. return time.ToString();
  386. }
  387. }
  388. private static ConcurrentDictionary<Type, Func<string, object>> _dicFromObject = new ConcurrentDictionary<Type, Func<string, object>>();
  389. public static object FromObject(this Type targetType, object value, Encoding encoding = null)
  390. {
  391. if (targetType == typeof(object)) return value;
  392. if (encoding == null) encoding = Encoding.UTF8;
  393. var valueIsNull = value == null;
  394. var valueType = valueIsNull ? typeof(string) : value.GetType();
  395. if (valueType == targetType) return value;
  396. if (valueType == typeof(byte[])) //byte[] -> guid
  397. {
  398. if (targetType == typeof(Guid))
  399. {
  400. var bytes = value as byte[];
  401. return Guid.TryParse(BitConverter.ToString(bytes, 0, Math.Min(bytes.Length, 36)).Replace("-", ""), out var tryguid) ? tryguid : Guid.Empty;
  402. }
  403. if (targetType == typeof(Guid?))
  404. {
  405. var bytes = value as byte[];
  406. return Guid.TryParse(BitConverter.ToString(bytes, 0, Math.Min(bytes.Length, 36)).Replace("-", ""), out var tryguid) ? (Guid?)tryguid : null;
  407. }
  408. }
  409. if (targetType == typeof(byte[])) //guid -> byte[]
  410. {
  411. if (valueIsNull) return null;
  412. if (valueType == typeof(Guid) || valueType == typeof(Guid?))
  413. {
  414. var bytes = new byte[16];
  415. var guidN = ((Guid)value).ToString("N");
  416. for (var a = 0; a < guidN.Length; a += 2)
  417. bytes[a / 2] = byte.Parse($"{guidN[a]}{guidN[a + 1]}", NumberStyles.HexNumber);
  418. return bytes;
  419. }
  420. return encoding.GetBytes(value.ToInvariantCultureToString());
  421. }
  422. else if (targetType.IsArray)
  423. {
  424. if (value is Array valueArr)
  425. {
  426. var targetElementType = targetType.GetElementType();
  427. var sourceArrLen = valueArr.Length;
  428. var target = Array.CreateInstance(targetElementType, sourceArrLen);
  429. for (var a = 0; a < sourceArrLen; a++) target.SetValue(targetElementType.FromObject(valueArr.GetValue(a), encoding), a);
  430. return target;
  431. }
  432. //if (value is IList valueList)
  433. //{
  434. // var targetElementType = targetType.GetElementType();
  435. // var sourceArrLen = valueList.Count;
  436. // var target = Array.CreateInstance(targetElementType, sourceArrLen);
  437. // for (var a = 0; a < sourceArrLen; a++) target.SetValue(targetElementType.FromObject(valueList[a], encoding), a);
  438. // return target;
  439. //}
  440. }
  441. var func = _dicFromObject.GetOrAdd(targetType, tt =>
  442. {
  443. if (tt == typeof(object)) return vs => vs;
  444. if (tt == typeof(string)) return vs => vs;
  445. if (tt == typeof(char[])) return vs => vs == null ? null : vs.ToCharArray();
  446. if (tt == typeof(char)) return vs => vs == null ? default(char) : vs.ToCharArray(0, 1).FirstOrDefault();
  447. if (tt == typeof(bool)) return vs =>
  448. {
  449. if (vs == null) return false;
  450. switch (vs.ToLower())
  451. {
  452. case "true":
  453. case "1":
  454. return true;
  455. }
  456. return false;
  457. };
  458. if (tt == typeof(bool?)) return vs =>
  459. {
  460. if (vs == null) return false;
  461. switch (vs.ToLower())
  462. {
  463. case "true":
  464. case "1":
  465. return true;
  466. case "false":
  467. case "0":
  468. return false;
  469. }
  470. return null;
  471. };
  472. if (tt == typeof(byte)) return vs => vs == null ? 0 : byte.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  473. if (tt == typeof(byte?)) return vs => vs == null ? null : byte.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (byte?)tryval : null;
  474. if (tt == typeof(decimal)) return vs => vs == null ? 0 : decimal.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  475. if (tt == typeof(decimal?)) return vs => vs == null ? null : decimal.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (decimal?)tryval : null;
  476. if (tt == typeof(double)) return vs => vs == null ? 0 : double.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  477. if (tt == typeof(double?)) return vs => vs == null ? null : double.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (double?)tryval : null;
  478. if (tt == typeof(float)) return vs => vs == null ? 0 : float.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  479. if (tt == typeof(float?)) return vs => vs == null ? null : float.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (float?)tryval : null;
  480. if (tt == typeof(int)) return vs => vs == null ? 0 : int.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  481. if (tt == typeof(int?)) return vs => vs == null ? null : int.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (int?)tryval : null;
  482. if (tt == typeof(long)) return vs => vs == null ? 0 : long.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  483. if (tt == typeof(long?)) return vs => vs == null ? null : long.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (long?)tryval : null;
  484. if (tt == typeof(sbyte)) return vs => vs == null ? 0 : sbyte.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  485. if (tt == typeof(sbyte?)) return vs => vs == null ? null : sbyte.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (sbyte?)tryval : null;
  486. if (tt == typeof(short)) return vs => vs == null ? 0 : short.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  487. if (tt == typeof(short?)) return vs => vs == null ? null : short.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (short?)tryval : null;
  488. if (tt == typeof(uint)) return vs => vs == null ? 0 : uint.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  489. if (tt == typeof(uint?)) return vs => vs == null ? null : uint.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (uint?)tryval : null;
  490. if (tt == typeof(ulong)) return vs => vs == null ? 0 : ulong.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  491. if (tt == typeof(ulong?)) return vs => vs == null ? null : ulong.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (ulong?)tryval : null;
  492. if (tt == typeof(ushort)) return vs => vs == null ? 0 : ushort.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  493. if (tt == typeof(ushort?)) return vs => vs == null ? null : ushort.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (ushort?)tryval : null;
  494. if (tt == typeof(DateTime)) return vs => vs == null ? DateTime.MinValue : DateTime.TryParse(vs, out var tryval) ? tryval : DateTime.MinValue;
  495. if (tt == typeof(DateTime?)) return vs => vs == null ? null : DateTime.TryParse(vs, out var tryval) ? (DateTime?)tryval : null;
  496. if (tt == typeof(DateTimeOffset)) return vs => vs == null ? DateTimeOffset.MinValue : DateTimeOffset.TryParse(vs, out var tryval) ? tryval : DateTimeOffset.MinValue;
  497. if (tt == typeof(DateTimeOffset?)) return vs => vs == null ? null : DateTimeOffset.TryParse(vs, out var tryval) ? (DateTimeOffset?)tryval : null;
  498. if (tt == typeof(TimeSpan)) return vs => vs == null ? TimeSpan.Zero : TimeSpan.TryParse(vs, out var tryval) ? tryval : TimeSpan.Zero;
  499. if (tt == typeof(TimeSpan?)) return vs => vs == null ? null : TimeSpan.TryParse(vs, out var tryval) ? (TimeSpan?)tryval : null;
  500. if (tt == typeof(Guid)) return vs => vs == null ? Guid.Empty : Guid.TryParse(vs, out var tryval) ? tryval : Guid.Empty;
  501. if (tt == typeof(Guid?)) return vs => vs == null ? null : Guid.TryParse(vs, out var tryval) ? (Guid?)tryval : null;
  502. if (tt == typeof(BigInteger)) return vs => vs == null ? 0 : BigInteger.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0;
  503. if (tt == typeof(BigInteger?)) return vs => vs == null ? null : BigInteger.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (BigInteger?)tryval : null;
  504. if (tt.NullableTypeOrThis().IsEnum)
  505. {
  506. var tttype = tt.NullableTypeOrThis();
  507. var ttdefval = tt.CreateInstanceGetDefaultValue();
  508. return vs =>
  509. {
  510. if (string.IsNullOrWhiteSpace(vs)) return ttdefval;
  511. return Enum.Parse(tttype, vs, true);
  512. };
  513. }
  514. var localTargetType = targetType;
  515. var localValueType = valueType;
  516. return vs =>
  517. {
  518. if (vs == null) return null;
  519. throw new NotSupportedException($"convert failed {localValueType.DisplayCsharp()} -> {localTargetType.DisplayCsharp()}");
  520. };
  521. });
  522. var valueStr = valueIsNull ? null : valueType == typeof(byte[]) ? encoding.GetString(value as byte[]) : value.ToInvariantCultureToString();
  523. return func(valueStr);
  524. }
  525. internal static string ToInvariantCultureToString(this object obj) => obj is string objstr ? objstr : string.Format(CultureInfo.InvariantCulture, @"{0}", obj);
  526. private static bool IsNullableType(this Type that) => that.IsArray == false && that?.FullName.StartsWith("System.Nullable`1[") == true;
  527. private static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GetGenericArguments().First() : that;
  528. internal static object CreateInstanceGetDefaultValue(this Type that)
  529. {
  530. if (that == null) return null;
  531. if (that == typeof(string)) return default(string);
  532. if (that == typeof(Guid)) return default(Guid);
  533. if (that == typeof(byte[])) return default(byte[]);
  534. if (that.IsArray) return Array.CreateInstance(that.GetElementType(), 0);
  535. if (that.IsInterface || that.IsAbstract) return null;
  536. var ctorParms = that.InternalGetTypeConstructor0OrFirst(false)?.GetParameters();
  537. if (ctorParms == null || ctorParms.Any() == false) return Activator.CreateInstance(that, true);
  538. return Activator.CreateInstance(that, ctorParms.Select(a => a.ParameterType.IsInterface ||
  539. a.ParameterType.IsAbstract ||
  540. a.ParameterType == typeof(string) ||
  541. a.ParameterType.IsArray ? null : Activator.CreateInstance(a.ParameterType, null)).ToArray());
  542. }
  543. private static ConcurrentDictionary<Type, ConstructorInfo> _dicInternalGetTypeConstructor0OrFirst = new ConcurrentDictionary<Type, ConstructorInfo>();
  544. private static ConstructorInfo InternalGetTypeConstructor0OrFirst(this Type that, bool isThrow = true)
  545. {
  546. var ret = _dicInternalGetTypeConstructor0OrFirst.GetOrAdd(that, tp =>
  547. tp.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null) ??
  548. tp.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault());
  549. if (ret == null && isThrow) throw new ArgumentException($"{that.FullName} has no method to access constructor");
  550. return ret;
  551. }
  552. private static string DisplayCsharp(this Type type, bool isNameSpace = true)
  553. {
  554. if (type == null) return null;
  555. if (type == typeof(void)) return "void";
  556. if (type.IsGenericParameter) return type.Name;
  557. if (type.IsArray) return $"{DisplayCsharp(type.GetElementType())}[]";
  558. var sb = new StringBuilder();
  559. var nestedType = type;
  560. while (nestedType.IsNested)
  561. {
  562. sb.Insert(0, ".").Insert(0, DisplayCsharp(nestedType.DeclaringType, false));
  563. nestedType = nestedType.DeclaringType;
  564. }
  565. if (isNameSpace && string.IsNullOrWhiteSpace(nestedType.Namespace) == false)
  566. sb.Insert(0, ".").Insert(0, nestedType.Namespace);
  567. if (type.IsGenericType == false)
  568. return sb.Append(type.Name).ToString();
  569. var genericParameters = type.GetGenericArguments();
  570. if (type.IsNested && type.DeclaringType.IsGenericType)
  571. {
  572. var dic = genericParameters.ToDictionary(a => a.Name);
  573. foreach (var nestedGenericParameter in type.DeclaringType.GetGenericArguments())
  574. if (dic.ContainsKey(nestedGenericParameter.Name))
  575. dic.Remove(nestedGenericParameter.Name);
  576. genericParameters = dic.Values.ToArray();
  577. }
  578. if (genericParameters.Any() == false)
  579. return sb.Append(type.Name).ToString();
  580. sb.Append(type.Name.Remove(type.Name.IndexOf('`'))).Append("<");
  581. var genericTypeIndex = 0;
  582. foreach (var genericType in genericParameters)
  583. {
  584. if (genericTypeIndex++ > 0) sb.Append(", ");
  585. sb.Append(DisplayCsharp(genericType, true));
  586. }
  587. return sb.Append(">").ToString();
  588. }
  589. /// <summary>
  590. /// 对象转换为字典
  591. /// </summary>
  592. /// <typeparam name="T"></typeparam>
  593. /// <param name="obj"></param>
  594. /// <returns></returns>
  595. public static Dictionary<string, string> ToDic<T>(this T obj) where T : class
  596. {
  597. Dictionary<string, string> map = new Dictionary<string, string>();
  598. var objSte = JsonConvert.SerializeObject(obj);
  599. map = JsonConvert.DeserializeObject<Dictionary<string, string>>(objSte);
  600. return map;
  601. }
  602. /// <summary>
  603. /// 字典转为实体
  604. /// </summary>
  605. /// <typeparam name="T"></typeparam>
  606. /// <param name="obj"></param>
  607. /// <returns></returns>
  608. public static T ToClass<T>(this Dictionary<string, string> obj)
  609. {
  610. var objSte = JsonConvert.SerializeObject(obj);
  611. var map = JsonConvert.DeserializeObject<T>(objSte);
  612. return map;
  613. }
  614. }
  615. public enum GetFormatterEnum
  616. {
  617. /// <summary>
  618. /// 默认类型
  619. /// </summary>
  620. Default = 0,
  621. /// <summary>
  622. /// yyyy
  623. /// </summary>
  624. yyyy = 4,
  625. /// <summary>
  626. /// yyyy-MM
  627. /// </summary>
  628. yyyyMM = 5,
  629. /// <summary>
  630. /// yyyy-MM-dd
  631. /// </summary>
  632. yyyyMMdd = 6,
  633. /// <summary>
  634. /// yyyy-MM-dd hh
  635. /// </summary>
  636. yyyyMMddhh = 7,
  637. /// <summary>
  638. /// yyyy-MM-dd hh:mm
  639. /// </summary>
  640. yyyyMMddhhmm = 8,
  641. /// <summary>
  642. /// yyyy-MM-dd hh:mm:ss
  643. /// </summary>
  644. yyyyMMddhhmmss = 9,
  645. /// <summary>
  646. /// yyyy-MM-dd hh:mm:ss:fffffff
  647. /// </summary>
  648. yyyyMMddhhmmssfffffff = 10,
  649. /// <summary>
  650. /// 用时间组成唯一值
  651. /// yyyyMMddhhmmssfffffff
  652. /// </summary>
  653. only = 11,
  654. }
  655. }