TypeExtension.cs 26 KB

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