Extensions.cs 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text.RegularExpressions;
  5. using System.Threading.Tasks;
  6. using Newtonsoft.Json;
  7. namespace Masuit.Tools
  8. {
  9. /// <summary>
  10. /// 扩展方法
  11. /// </summary>
  12. public static class Extensions
  13. {
  14. #region SyncForEach
  15. /// <summary>
  16. /// 遍历数组
  17. /// </summary>
  18. /// <param name="objs"></param>
  19. /// <param name="action">回调方法</param>
  20. public static void ForEach(this object[] objs, Action<object> action)
  21. {
  22. foreach (var o in objs)
  23. {
  24. action(o);
  25. }
  26. }
  27. /// <summary>
  28. /// 遍历IEnumerable
  29. /// </summary>
  30. /// <param name="objs"></param>
  31. /// <param name="action">回调方法</param>
  32. public static void ForEach(this IEnumerable<object> objs, Action<object> action)
  33. {
  34. foreach (var o in objs)
  35. {
  36. action(o);
  37. }
  38. }
  39. /// <summary>
  40. /// 遍历集合
  41. /// </summary>
  42. /// <param name="objs"></param>
  43. /// <param name="action">回调方法</param>
  44. public static void ForEach(this IList<object> objs, Action<object> action)
  45. {
  46. foreach (var o in objs)
  47. {
  48. action(o);
  49. }
  50. }
  51. /// <summary>
  52. /// 遍历数组
  53. /// </summary>
  54. /// <param name="objs"></param>
  55. /// <param name="action">回调方法</param>
  56. /// <typeparam name="T"></typeparam>
  57. public static void ForEach<T>(this T[] objs, Action<T> action)
  58. {
  59. foreach (var o in objs)
  60. {
  61. action(o);
  62. }
  63. }
  64. /// <summary>
  65. /// 遍历IEnumerable
  66. /// </summary>
  67. /// <param name="objs"></param>
  68. /// <param name="action">回调方法</param>
  69. /// <typeparam name="T"></typeparam>
  70. public static void ForEach<T>(this IEnumerable<T> objs, Action<T> action)
  71. {
  72. foreach (var o in objs)
  73. {
  74. action(o);
  75. }
  76. }
  77. /// <summary>
  78. /// 遍历List
  79. /// </summary>
  80. /// <param name="objs"></param>
  81. /// <param name="action">回调方法</param>
  82. /// <typeparam name="T"></typeparam>
  83. public static void ForEach<T>(this IList<T> objs, Action<T> action)
  84. {
  85. foreach (var o in objs)
  86. {
  87. action(o);
  88. }
  89. }
  90. /// <summary>
  91. /// 遍历数组并返回一个新的List
  92. /// </summary>
  93. /// <param name="objs"></param>
  94. /// <param name="action">回调方法</param>
  95. /// <returns></returns>
  96. public static IEnumerable<T> ForEach<T>(this object[] objs, Func<object, T> action)
  97. {
  98. foreach (var o in objs)
  99. {
  100. yield return action(o);
  101. }
  102. }
  103. /// <summary>
  104. /// 遍历IEnumerable并返回一个新的List
  105. /// </summary>
  106. /// <param name="objs"></param>
  107. /// <param name="action">回调方法</param>
  108. /// <typeparam name="T"></typeparam>
  109. /// <returns></returns>
  110. public static IEnumerable<T> ForEach<T>(this IEnumerable<object> objs, Func<object, T> action)
  111. {
  112. foreach (var o in objs)
  113. {
  114. yield return action(o);
  115. }
  116. }
  117. /// <summary>
  118. /// 遍历List并返回一个新的List
  119. /// </summary>
  120. /// <param name="objs"></param>
  121. /// <param name="action">回调方法</param>
  122. /// <typeparam name="T"></typeparam>
  123. /// <returns></returns>
  124. public static IEnumerable<T> ForEach<T>(this IList<object> objs, Func<object, T> action)
  125. {
  126. foreach (var o in objs)
  127. {
  128. yield return action(o);
  129. }
  130. }
  131. /// <summary>
  132. /// 遍历数组并返回一个新的List
  133. /// </summary>
  134. /// <param name="objs"></param>
  135. /// <param name="action">回调方法</param>
  136. /// <typeparam name="T"></typeparam>
  137. /// <returns></returns>
  138. public static IEnumerable<T> ForEach<T>(this T[] objs, Func<T, T> action)
  139. {
  140. foreach (var o in objs)
  141. {
  142. yield return action(o);
  143. }
  144. }
  145. /// <summary>
  146. /// 遍历IEnumerable并返回一个新的List
  147. /// </summary>
  148. /// <param name="objs"></param>
  149. /// <param name="action">回调方法</param>
  150. /// <typeparam name="T"></typeparam>
  151. /// <returns></returns>
  152. public static IEnumerable<T> ForEach<T>(this IEnumerable<T> objs, Func<T, T> action)
  153. {
  154. foreach (var o in objs)
  155. {
  156. yield return action(o);
  157. }
  158. }
  159. /// <summary>
  160. /// 遍历List并返回一个新的List
  161. /// </summary>
  162. /// <param name="objs"></param>
  163. /// <param name="action">回调方法</param>
  164. /// <typeparam name="T"></typeparam>
  165. /// <returns></returns>
  166. public static IEnumerable<T> ForEach<T>(this IList<T> objs, Func<T, T> action)
  167. {
  168. foreach (var o in objs)
  169. {
  170. yield return action(o);
  171. }
  172. }
  173. #endregion
  174. #region AsyncForEach
  175. /// <summary>
  176. /// 遍历数组
  177. /// </summary>
  178. /// <param name="objs"></param>
  179. /// <param name="action">回调方法</param>
  180. public static async void ForEachAsync(this object[] objs, Action<object> action)
  181. {
  182. await Task.Run(() =>
  183. {
  184. Parallel.ForEach(objs, action);
  185. });
  186. }
  187. /// <summary>
  188. /// 遍历数组
  189. /// </summary>
  190. /// <param name="objs"></param>
  191. /// <param name="action">回调方法</param>
  192. /// <typeparam name="T"></typeparam>
  193. public static async void ForEachAsync<T>(this T[] objs, Action<T> action)
  194. {
  195. await Task.Run(() =>
  196. {
  197. Parallel.ForEach(objs, action);
  198. });
  199. }
  200. /// <summary>
  201. /// 遍历IEnumerable
  202. /// </summary>
  203. /// <param name="objs"></param>
  204. /// <param name="action">回调方法</param>
  205. /// <typeparam name="T"></typeparam>
  206. public static async void ForEachAsync<T>(this IEnumerable<T> objs, Action<T> action)
  207. {
  208. await Task.Run(() =>
  209. {
  210. Parallel.ForEach(objs, action);
  211. });
  212. }
  213. /// <summary>
  214. /// 遍历List
  215. /// </summary>
  216. /// <param name="objs"></param>
  217. /// <param name="action">回调方法</param>
  218. /// <typeparam name="T"></typeparam>
  219. public static async void ForEachAsync<T>(this IList<T> objs, Action<T> action)
  220. {
  221. await Task.Run(() =>
  222. {
  223. Parallel.ForEach(objs, action);
  224. });
  225. }
  226. #endregion
  227. #region Map
  228. /// <summary>
  229. /// 映射到目标类型(浅克隆)
  230. /// </summary>
  231. /// <param name="source">源</param>
  232. /// <typeparam name="TDestination">目标类型</typeparam>
  233. /// <returns>目标类型</returns>
  234. public static TDestination MapTo<TDestination>(this object source) where TDestination : new()
  235. {
  236. TDestination dest = new TDestination();
  237. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(source)); });
  238. return dest;
  239. }
  240. /// <summary>
  241. /// 映射到目标类型(浅克隆)
  242. /// </summary>
  243. /// <param name="source">源</param>
  244. /// <typeparam name="TDestination">目标类型</typeparam>
  245. /// <returns>目标类型</returns>
  246. public static async Task<TDestination> MapToAsync<TDestination>(this object source) where TDestination : new()
  247. {
  248. return await Task.Run(() =>
  249. {
  250. TDestination dest = new TDestination();
  251. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(source)); });
  252. return dest;
  253. });
  254. }
  255. /// <summary>
  256. /// 映射到目标类型(深克隆)
  257. /// </summary>
  258. /// <param name="source">源</param>
  259. /// <typeparam name="TDestination">目标类型</typeparam>
  260. /// <returns>目标类型</returns>
  261. public static TDestination Map<TDestination>(this object source) where TDestination : new() => JsonConvert.DeserializeObject<TDestination>(JsonConvert.SerializeObject(source));
  262. /// <summary>
  263. /// 映射到目标类型(深克隆)
  264. /// </summary>
  265. /// <param name="source">源</param>
  266. /// <typeparam name="TDestination">目标类型</typeparam>
  267. /// <returns>目标类型</returns>
  268. public static async Task<TDestination> MapAsync<TDestination>(this object source) where TDestination : new() => await Task.Run(() => JsonConvert.DeserializeObject<TDestination>(JsonConvert.SerializeObject(source)));
  269. /// <summary>
  270. /// 复制一个新的对象
  271. /// </summary>
  272. /// <typeparam name="T"></typeparam>
  273. /// <param name="source"></param>
  274. /// <returns></returns>
  275. public static T Copy<T>(this T source) where T : new()
  276. {
  277. T dest = new T();
  278. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(source)); });
  279. return dest;
  280. }
  281. /// <summary>
  282. /// 复制到一个现有对象
  283. /// </summary>
  284. /// <typeparam name="T"></typeparam>
  285. /// <param name="source">源对象</param>
  286. /// <param name="dest">目标对象</param>
  287. /// <returns></returns>
  288. public static T CopyTo<T>(this T source, T dest) where T : new()
  289. {
  290. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(source)); });
  291. return dest;
  292. }
  293. /// <summary>
  294. /// 复制一个新的对象
  295. /// </summary>
  296. /// <typeparam name="T"></typeparam>
  297. /// <param name="source"></param>
  298. /// <returns></returns>
  299. public static async Task<T> CopyAsync<T>(this T source) where T : new() =>
  300. await Task.Run(() =>
  301. {
  302. T dest = new T();
  303. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(source)); });
  304. return dest;
  305. });
  306. /// <summary>
  307. /// 映射到目标类型的集合
  308. /// </summary>
  309. /// <param name="source">源</param>
  310. /// <typeparam name="TDestination">目标类型</typeparam>
  311. /// <returns>目标类型集合</returns>
  312. public static IEnumerable<TDestination> ToList<TDestination>(this object[] source) where TDestination : new()
  313. {
  314. foreach (var o in source)
  315. {
  316. var dest = new TDestination();
  317. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(o)); });
  318. yield return dest;
  319. }
  320. }
  321. /// <summary>
  322. /// 映射到目标类型的集合
  323. /// </summary>
  324. /// <param name="source">源</param>
  325. /// <typeparam name="TDestination">目标类型</typeparam>
  326. /// <returns>目标类型集合</returns>
  327. public static async Task<IEnumerable<TDestination>> ToListAsync<TDestination>(this object[] source) where TDestination : new()
  328. {
  329. return await Task.Run(() =>
  330. {
  331. IList<TDestination> list = new List<TDestination>();
  332. foreach (var o in source)
  333. {
  334. var dest = new TDestination();
  335. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(o)); });
  336. list.Add(dest);
  337. }
  338. return list;
  339. });
  340. }
  341. /// <summary>
  342. /// 映射到目标类型的集合
  343. /// </summary>
  344. /// <param name="source">源</param>
  345. /// <typeparam name="TDestination">目标类型</typeparam>
  346. /// <returns>目标类型集合</returns>
  347. public static IEnumerable<TDestination> ToList<TDestination>(this IList<object> source) where TDestination : new()
  348. {
  349. foreach (var o in source)
  350. {
  351. var dest = new TDestination();
  352. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(o)); });
  353. yield return dest;
  354. }
  355. }
  356. /// <summary>
  357. /// 映射到目标类型的集合
  358. /// </summary>
  359. /// <param name="source">源</param>
  360. /// <typeparam name="TDestination">目标类型</typeparam>
  361. /// <returns>目标类型集合</returns>
  362. public static async Task<IEnumerable<TDestination>> ToListAsync<TDestination>(this IList<object> source) where TDestination : new()
  363. {
  364. return await Task.Run(() =>
  365. {
  366. IList<TDestination> list = new List<TDestination>();
  367. foreach (var o in source)
  368. {
  369. var dest = new TDestination();
  370. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(o)); });
  371. list.Add(dest);
  372. }
  373. return list;
  374. });
  375. }
  376. /// <summary>
  377. /// 映射到目标类型的集合
  378. /// </summary>
  379. /// <param name="source">源</param>
  380. /// <typeparam name="TDestination">目标类型</typeparam>
  381. /// <returns>目标类型集合</returns>
  382. public static IEnumerable<TDestination> ToList<TDestination>(this IEnumerable<object> source) where TDestination : new()
  383. {
  384. foreach (var o in source)
  385. {
  386. var dest = new TDestination();
  387. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(o)); });
  388. yield return dest;
  389. }
  390. }
  391. /// <summary>
  392. /// 映射到目标类型的集合
  393. /// </summary>
  394. /// <param name="source">源</param>
  395. /// <typeparam name="TDestination">目标类型</typeparam>
  396. /// <returns>目标类型集合</returns>
  397. public static async Task<IEnumerable<TDestination>> ToListAsync<TDestination>(this IEnumerable<object> source) where TDestination : new()
  398. {
  399. return await Task.Run(() =>
  400. {
  401. IList<TDestination> list = new List<TDestination>();
  402. foreach (var o in source)
  403. {
  404. var dest = new TDestination();
  405. dest.GetType().GetProperties().ForEach(p => { p.SetValue(dest, source.GetType().GetProperty(p.Name)?.GetValue(o)); });
  406. list.Add(dest);
  407. }
  408. return list;
  409. });
  410. }
  411. #endregion
  412. /// <summary>
  413. /// 转换成json字符串
  414. /// </summary>
  415. /// <param name="source"></param>
  416. /// <returns></returns>
  417. public static string ToJsonString(this object source) => JsonConvert.SerializeObject(source, new JsonSerializerSettings()
  418. {
  419. ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
  420. Formatting = Formatting.Indented
  421. });
  422. /// <summary>
  423. /// 转换成json字符串
  424. /// </summary>
  425. /// <param name="source"></param>
  426. /// <returns></returns>
  427. public static async Task<string> ToJsonStringAsync(this object source) => await Task.Run(() => JsonConvert.SerializeObject(source, new JsonSerializerSettings()
  428. {
  429. ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
  430. Formatting = Formatting.Indented
  431. }));
  432. #region UBB、HTML互转
  433. /// <summary>
  434. /// UBB代码处理函数
  435. /// </summary>
  436. /// <param name="ubbStr">输入UBB字符串</param>
  437. /// <returns>输出html字符串</returns>
  438. public static string UbbToHtml(this string ubbStr)
  439. {
  440. Regex r;
  441. Match m;
  442. #region 处理空格
  443. ubbStr = ubbStr.Replace(" ", "&nbsp;");
  444. #endregion
  445. #region 处理&符
  446. ubbStr = ubbStr.Replace("&", "&amp;");
  447. #endregion
  448. #region 处理单引号
  449. ubbStr = ubbStr.Replace("'", "’");
  450. #endregion
  451. #region 处理双引号
  452. ubbStr = ubbStr.Replace("\"", "&quot;");
  453. #endregion
  454. #region html标记符
  455. ubbStr = ubbStr.Replace("<", "&lt;");
  456. ubbStr = ubbStr.Replace(">", "&gt;");
  457. #endregion
  458. #region 处理换行
  459. //处理换行,在每个新行的前面添加两个全角空格
  460. r = new Regex(@"(\r\n((&nbsp;)| )+)(?<正文>\S+)", RegexOptions.IgnoreCase);
  461. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<BR>  " + m.Groups["正文"]);
  462. //处理换行,在每个新行的前面添加两个全角空格
  463. ubbStr = ubbStr.Replace("\r\n", "<BR>");
  464. #endregion
  465. #region 处[b][/b]标记
  466. r = new Regex(@"(\[b\])([ \S\t]*?)(\[\/b\])", RegexOptions.IgnoreCase);
  467. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<B>" + m.Groups[2] + "</B>");
  468. #endregion
  469. #region 处[i][/i]标记
  470. r = new Regex(@"(\[i\])([ \S\t]*?)(\[\/i\])", RegexOptions.IgnoreCase);
  471. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<I>" + m.Groups[2] + "</I>");
  472. #endregion
  473. #region 处[u][/u]标记
  474. r = new Regex(@"(\[U\])([ \S\t]*?)(\[\/U\])", RegexOptions.IgnoreCase);
  475. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<U>" + m.Groups[2] + "</U>");
  476. #endregion
  477. #region 处[p][/p]标记
  478. //处[p][/p]标记
  479. r = new Regex(@"((\r\n)*\[p\])(.*?)((\r\n)*\[\/p\])", RegexOptions.IgnoreCase | RegexOptions.Singleline);
  480. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<P class=\"pstyle\">" + m.Groups[3] + "</P>");
  481. #endregion
  482. #region 处[sup][/sup]标记
  483. //处[sup][/sup]标记
  484. r = new Regex(@"(\[sup\])([ \S\t]*?)(\[\/sup\])", RegexOptions.IgnoreCase);
  485. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<SUP>" + m.Groups[2] + "</SUP>");
  486. #endregion
  487. #region 处[sub][/sub]标记
  488. //处[sub][/sub]标记
  489. r = new Regex(@"(\[sub\])([ \S\t]*?)(\[\/sub\])", RegexOptions.IgnoreCase);
  490. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<SUB>" + m.Groups[2] + "</SUB>");
  491. #endregion
  492. #region 处标记
  493. //处标记
  494. r = new Regex(@"(\[url\])([ \S\t]*?)(\[\/url\])", RegexOptions.IgnoreCase);
  495. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  496. {
  497. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<A href=\"" + m.Groups[2] + "\" target=\"_blank\">" + m.Groups[2] + "</A>");
  498. }
  499. #endregion
  500. #region 处[url=xxx][/url]标记
  501. //处[url=xxx][/url]标记
  502. r = new Regex(@"(\[url=([ \S\t]+)\])([ \S\t]*?)(\[\/url\])", RegexOptions.IgnoreCase);
  503. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  504. {
  505. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<A href=\"" + m.Groups[2] + "\" target=\"_blank\">" + m.Groups[3] + "</A>");
  506. }
  507. #endregion
  508. #region 处[email][/email]标记
  509. //处[email][/email]标记
  510. r = new Regex(@"(\[email\])([ \S\t]*?)(\[\/email\])", RegexOptions.IgnoreCase);
  511. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  512. {
  513. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<A href=\"mailto:" + m.Groups[2] + "\" target=\"_blank\">" + m.Groups[2] + "</A>");
  514. }
  515. #endregion
  516. #region 处[email=xxx][/email]标记
  517. //处[email=xxx][/email]标记
  518. r = new Regex(@"(\[email=([ \S\t]+)\])([ \S\t]*?)(\[\/email\])", RegexOptions.IgnoreCase);
  519. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  520. {
  521. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<A href=\"mailto:" + m.Groups[2] + "\" target=\"_blank\">" + m.Groups[3] + "</A>");
  522. }
  523. #endregion
  524. #region 处[size=x][/size]标记
  525. //处[size=x][/size]标记
  526. r = new Regex(@"(\[size=([1-7])\])([ \S\t]*?)(\[\/size\])", RegexOptions.IgnoreCase);
  527. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  528. {
  529. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<FONT SIZE=" + m.Groups[2] + ">" + m.Groups[3] + "</FONT>");
  530. }
  531. #endregion
  532. #region 处[color=x][/color]标记
  533. //处[color=x][/color]标记
  534. r = new Regex(@"(\[color=([\S]+)\])([ \S\t]*?)(\[\/color\])", RegexOptions.IgnoreCase);
  535. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  536. {
  537. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<FONT COLOR=" + m.Groups[2] + ">" + m.Groups[3] + "</FONT>");
  538. }
  539. #endregion
  540. #region 处[font=x][/font]标记
  541. //处[font=x][/font]标记
  542. r = new Regex(@"(\[font=([\S]+)\])([ \S\t]*?)(\[\/font\])", RegexOptions.IgnoreCase);
  543. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  544. {
  545. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<FONT FACE=" + m.Groups[2] + ">" + m.Groups[3] + "</FONT>");
  546. }
  547. #endregion
  548. #region 处理图片链接
  549. //处理图片链接
  550. r = new Regex("\\[picture\\](\\d+?)\\[\\/picture\\]", RegexOptions.IgnoreCase);
  551. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  552. {
  553. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<A href=\"ShowImage.aspx?Type=ALL&Action=forumImage&ImageID=" + m.Groups[1] + "\" target=\"_blank\"><IMG border=0 Title=\"点击打开新窗口查看\" src=\"ShowImage.aspx?Action=forumImage&ImageID=" + m.Groups[1] + "\"></A>");
  554. }
  555. #endregion
  556. #region 处理[align=x][/align]
  557. //处理[align=x][/align]
  558. r = new Regex(@"(\[align=([\S]+)\])([ \S\t]*?)(\[\/align\])", RegexOptions.IgnoreCase);
  559. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  560. {
  561. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<P align=" + m.Groups[2] + ">" + m.Groups[3] + "</P>");
  562. }
  563. #endregion
  564. #region 处[H=x][/H]标记
  565. //处[H=x][/H]标记
  566. r = new Regex(@"(\[H=([1-6])\])([ \S\t]*?)(\[\/H\])", RegexOptions.IgnoreCase);
  567. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  568. {
  569. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<H" + m.Groups[2] + ">" + m.Groups[3] + "</H" + m.Groups[2] + ">");
  570. }
  571. #endregion
  572. #region 处理[list=x][*][/list]
  573. //处理[list=x][*][/list]
  574. r = new Regex(@"(\[list(=(A|a|I|i| ))?\]([ \S\t]*)\r\n)((\[\*\]([ \S\t]*\r\n))*?)(\[\/list\])", RegexOptions.IgnoreCase);
  575. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  576. {
  577. string strLi = m.Groups[5].ToString();
  578. Regex rLi = new Regex(@"\[\*\]([ \S\t]*\r\n?)", RegexOptions.IgnoreCase);
  579. Match mLi;
  580. for (mLi = rLi.Match(strLi); mLi.Success; mLi = mLi.NextMatch()) strLi = strLi.Replace(mLi.Groups[0].ToString(), "<LI>" + mLi.Groups[1]);
  581. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<UL TYPE=\"" + m.Groups[3] + "\"><B>" + m.Groups[4] + "</B>" + strLi + "</UL>");
  582. }
  583. #endregion
  584. #region 处[SHADOW=x][/SHADOW]标记
  585. //处[SHADOW=x][/SHADOW]标记
  586. r = new Regex(@"(\[SHADOW=)(\d*?),(#*\w*?),(\d*?)\]([\S\t]*?)(\[\/SHADOW\])", RegexOptions.IgnoreCase);
  587. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  588. {
  589. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<TABLE WIDTH=" + m.Groups[2] + "STYLE=FILTER:SHADOW(COLOR=" + m.Groups[3] + ",STRENGTH=" + m.Groups[4] + ")>" + m.Groups[5] + "</TABLE>");
  590. }
  591. #endregion
  592. #region 处[glow=x][/glow]标记
  593. //处[glow=x][/glow]标记
  594. r = new Regex(@"(\[glow=)(\d*?),(#*\w*?),(\d*?)\]([\S\t]*?)(\[\/glow\])", RegexOptions.IgnoreCase);
  595. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  596. {
  597. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<TABLE WIDTH=" + m.Groups[2] + " STYLE=FILTER:GLOW(COLOR=" + m.Groups[3] + ", STRENGTH=" + m.Groups[4] + ")>" + m.Groups[5] + "</TABLE>");
  598. }
  599. #endregion
  600. #region 处[center][/center]标记
  601. r = new Regex(@"(\[center\])([ \S\t]*?)(\[\/center\])", RegexOptions.IgnoreCase);
  602. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<CENTER>" + m.Groups[2] + "</CENTER>");
  603. #endregion
  604. #region 处[ IMG][ /IMG]标记
  605. r = new Regex(@"(\[IMG\])(http|https|ftp):\/\/([ \S\t]*?)(\[\/IMG\])", RegexOptions.IgnoreCase);
  606. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<br><a onfocus=this.blur() href=" + m.Groups[2] + "://" + m.Groups[3] + " target=_blank><IMG SRC=" + m.Groups[2] + "://" + m.Groups[3] + " border=0 alt=按此在新窗口浏览图片 onload=javascript:if(screen.width-333<this.width)this.width=screen.width-333></a>");
  607. #endregion
  608. #region 处[em]标记
  609. r = new Regex(@"(\[em([\S\t]*?)\])", RegexOptions.IgnoreCase);
  610. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<img src=pic/em" + m.Groups[2] + ".gif border=0 align=middle>");
  611. #endregion
  612. #region 处[flash=x][/flash]标记
  613. //处[mp=x][/mp]标记
  614. r = new Regex(@"(\[flash=)(\d*?),(\d*?)\]([\S\t]*?)(\[\/flash\])", RegexOptions.IgnoreCase);
  615. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  616. {
  617. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<a href=" + m.Groups[4] + " TARGET=_blank><IMG SRC=pic/swf.gif border=0 alt=点击开新窗口欣赏该FLASH动画!> [全屏欣赏]</a><br><br><OBJECT codeBase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0 classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 width=" + m.Groups[2] + " height=" + m.Groups[3] + "><PARAM NAME=movie VALUE=" + m.Groups[4] + "><PARAM NAME=quality VALUE=high><param name=menu value=false><embed src=" + m.Groups[4] + " quality=high menu=false pluginspage=http://www.macromedia.com/go/getflashplayer type=application/x-shockwave-flash width=" + m.Groups[2] + " height=" + m.Groups[3] + ">" + m.Groups[4] + "</embed></OBJECT>");
  618. }
  619. #endregion
  620. #region 处[dir=x][/dir]标记
  621. //处[dir=x][/dir]标记
  622. r = new Regex(@"(\[dir=)(\d*?),(\d*?)\]([\S\t]*?)(\[\/dir\])", RegexOptions.IgnoreCase);
  623. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  624. {
  625. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<object classid=clsid:166B1BCA-3F9C-11CF-8075-444553540000 codebase=http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=7,0,2,0 width=" + m.Groups[2] + " height=" + m.Groups[3] + "><param name=src value=" + m.Groups[4] + "><embed src=" + m.Groups[4] + " pluginspage=http://www.macromedia.com/shockwave/download/ width=" + m.Groups[2] + " height=" + m.Groups[3] + "></embed></object>");
  626. }
  627. #endregion
  628. #region 处[rm=x][/rm]标记
  629. //处[rm=x][/rm]标记
  630. r = new Regex(@"(\[rm=)(\d*?),(\d*?)\]([\S\t]*?)(\[\/rm\])", RegexOptions.IgnoreCase);
  631. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  632. {
  633. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<OBJECT classid=clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA class=OBJECT id=RAOCX width=" + m.Groups[2] + " height=" + m.Groups[3] + "><PARAM NAME=SRC VALUE=" + m.Groups[4] + "><PARAM NAME=CONSOLE VALUE=Clip1><PARAM NAME=CONTROLS VALUE=imagewindow><PARAM NAME=AUTOSTART VALUE=true></OBJECT><br><OBJECT classid=CLSID:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA height=32 id=video2 width=" + m.Groups[2] + "><PARAM NAME=SRC VALUE=" + m.Groups[4] + "><PARAM NAME=AUTOSTART VALUE=-1><PARAM NAME=CONTROLS VALUE=controlpanel><PARAM NAME=CONSOLE VALUE=Clip1></OBJECT>");
  634. }
  635. #endregion
  636. #region 处[mp=x][/mp]标记
  637. //处[mp=x][/mp]标记
  638. r = new Regex(@"(\[mp=)(\d*?),(\d*?)\]([\S\t]*?)(\[\/mp\])", RegexOptions.IgnoreCase);
  639. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  640. {
  641. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<object align=middle classid=CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95 class=OBJECT id=MediaPlayer width=" + m.Groups[2] + " height=" + m.Groups[3] + " ><param name=ShowStatusBar value=-1><param name=Filename value=" + m.Groups[4] + "><embed type=application/x-oleobject codebase=http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701 flename=mp src=" + m.Groups[4] + " width=" + m.Groups[2] + " height=" + m.Groups[3] + "></embed></object>");
  642. }
  643. #endregion
  644. #region 处[qt=x][/qt]标记
  645. //处[qt=x][/qt]标记
  646. r = new Regex(@"(\[qt=)(\d*?),(\d*?)\]([\S\t]*?)(\[\/qt\])", RegexOptions.IgnoreCase);
  647. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  648. {
  649. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<embed src=" + m.Groups[4] + " width=" + m.Groups[2] + " height=" + m.Groups[3] + " autoplay=true loop=false controller=true playeveryframe=false cache=false scale=TOFIT bgcolor=#000000 kioskmode=false targetcache=false pluginspage=http://www.apple.com/quicktime/>");
  650. }
  651. #endregion
  652. #region 处[QUOTE][/QUOTE]标记
  653. r = new Regex(@"(\[QUOTE\])([ \S\t]*?)(\[\/QUOTE\])", RegexOptions.IgnoreCase);
  654. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<div style='border:#CCCCCC 1px dashed; width:94%; color:#999999; padding:3px; background:#F8F8F8'>" + m.Groups[2] + "</div><br /> ");
  655. #endregion
  656. #region 处[move][/move]标记
  657. r = new Regex(@"(\[move\])([ \S\t]*?)(\[\/move\])", RegexOptions.IgnoreCase);
  658. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<MARQUEE scrollamount=3>" + m.Groups[2] + "</MARQUEE>");
  659. #endregion
  660. #region 处[FLY][/FLY]标记
  661. r = new Regex(@"(\[FLY\])([ \S\t]*?)(\[\/FLY\])", RegexOptions.IgnoreCase);
  662. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch()) ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<MARQUEE width=80% behavior=alternate scrollamount=3>" + m.Groups[2] + "</MARQUEE>");
  663. #endregion
  664. #region 处[image][/image]标记
  665. //处[image][/image]标记
  666. r = new Regex(@"(\[image\])([ \S\t]*?)(\[\/image\])", RegexOptions.IgnoreCase);
  667. for (m = r.Match(ubbStr); m.Success; m = m.NextMatch())
  668. {
  669. ubbStr = ubbStr.Replace(m.Groups[0].ToString(), "<img src=\"" + m.Groups[2] + "\" border=0 align=middle><br>");
  670. }
  671. #endregion
  672. return ubbStr;
  673. }
  674. /// <summary>
  675. /// UBB代码处理函数
  676. /// </summary>
  677. /// <param name="ubbStr">输入UBB字符串</param>
  678. /// <returns>输出html字符串</returns>
  679. public static async Task<string> UbbToHtmlAsync(this string ubbStr) => await Task.Run(() => UbbToHtml(ubbStr));
  680. /// <summary>
  681. /// UBB转HTML方式2
  682. /// </summary>
  683. /// <param name="ubbStr">UBB 代码</param>
  684. /// <returns>HTML代码</returns>
  685. public static string UbbToHtml2(this string ubbStr)
  686. {
  687. ubbStr = ubbStr.Replace("&", "&amp;");
  688. ubbStr = ubbStr.Replace("<", "&lt;");
  689. ubbStr = ubbStr.Replace(">", "&gt;");
  690. ubbStr = ubbStr.Replace(" ", "&nbsp;"); //空格
  691. ubbStr = ubbStr.Replace("\n", "<br>"); //回车
  692. Regex my = new Regex(@"(\[IMG\])(.[^\[]*)(\[\/IMG\])", RegexOptions.IgnoreCase);
  693. ubbStr = my.Replace(ubbStr, @"<a href=""$2"" target=_blank><IMG SRC=""$2"" border=0 alt=按此在新窗口浏览图片 onload=""javascript:if(this.width>screen.width-333)this.width=screen.width-333""></a>");
  694. my = new Regex(@"\[DIR=*([0-9]*),*([0-9]*)\](.[^\[]*)\[\/DIR]", RegexOptions.IgnoreCase);
  695. ubbStr = my.Replace(ubbStr, @"<object classid=clsid:166B1BCA-3F9C-11CF-8075-444553540000 codebase=http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=7,0,2,0 width=$1 height=$2><param name=src value=$3><embed src=$3 pluginspage=http://www.macromedia.com/shockwave/download/ width=$1 height=$2></embed></object>");
  696. my = new Regex(@"\[QT=*([0-9]*),*([0-9]*)\](.[^\[]*)\[\/QT]", RegexOptions.IgnoreCase);
  697. ubbStr = my.Replace(ubbStr, @"<embed src=$3 width=$1 height=$2 autoplay=true loop=false controller=true playeveryframe=false cache=false scale=TOFIT bgcolor=#000000 kioskmode=false targetcache=false pluginspage=http://www.apple.com/quicktime/>");
  698. my = new Regex(@"\[MP=*([0-9]*),*([0-9]*)\](.[^\[]*)\[\/MP]", RegexOptions.IgnoreCase);
  699. ubbStr = my.Replace(ubbStr, @"<object align=middle classid=CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95 class=OBJECT id=MediaPlayer width=$1 height=$2 ><param name=ShowStatusBar value=-1><param name=Filename value=$3><embed type=application/x-oleobject codebase=http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701 flename=mp src=$3 width=$1 height=$2></embed></object>");
  700. my = new Regex(@"\[RM=*([0-9]*),*([0-9]*)\](.[^\[]*)\[\/RM]", RegexOptions.IgnoreCase);
  701. ubbStr = my.Replace(ubbStr, @"<OBJECT classid=clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA class=OBJECT id=RAOCX width=$1 height=$2><PARAM NAME=SRC VALUE=$3><PARAM NAME=CONSOLE VALUE=Clip1><PARAM NAME=CONTROLS VALUE=imagewindow><PARAM NAME=AUTOSTART VALUE=true></OBJECT><br><OBJECT classid=CLSID:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA height=32 id=video2 width=$1><PARAM NAME=SRC VALUE=$3><PARAM NAME=AUTOSTART VALUE=-1><PARAM NAME=CONTROLS VALUE=controlpanel><PARAM NAME=CONSOLE VALUE=Clip1></OBJECT>");
  702. my = new Regex(@"(\[FLASH\])(.[^\[]*)(\[\/FLASH\])", RegexOptions.IgnoreCase);
  703. ubbStr = my.Replace(ubbStr, @"<OBJECT codeBase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=4,0,2,0 classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 width=500 height=400><PARAM NAME=movie VALUE=""$2""><PARAM NAME=quality VALUE=high><embed src=""$2"" quality=high pluginspage='http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash' type='application/x-shockwave-flash' width=500 height=400>$2</embed></OBJECT>");
  704. my = new Regex(@"(\[ZIP\])(.[^\[]*)(\[\/ZIP\])", RegexOptions.IgnoreCase);
  705. ubbStr = my.Replace(ubbStr, @"<br><IMG SRC=pic/zip.gif border=0> <a href=""$2"">点击下载该文件</a>");
  706. my = new Regex(@"(\[RAR\])(.[^\[]*)(\[\/RAR\])", RegexOptions.IgnoreCase);
  707. ubbStr = my.Replace(ubbStr, @"<br><IMG SRC=pic/rar.gif border=0> <a href=""$2"">点击下载该文件</a>");
  708. my = new Regex(@"(\[UPLOAD=(.[^\[]*)\])(.[^\[]*)(\[\/UPLOAD\])", RegexOptions.IgnoreCase);
  709. ubbStr = my.Replace(ubbStr, @"<br><IMG SRC=""pic/$2.gif"" border=0>此主题相关图片如下:<br><A HREF=""$3"" TARGET=_blank><IMG SRC=""$3"" border=0 alt=按此在新窗口浏览图片 onload=""javascript:if(this.width>screen.width-333)this.width=screen.width-333""></A>");
  710. my = new Regex(@"(\[URL\])(http:\/\/.[^\[]*)(\[\/URL\])", RegexOptions.IgnoreCase);
  711. ubbStr = my.Replace(ubbStr, @"<A HREF=""$2"" TARGET=_blank>$2</A>");
  712. my = new Regex(@"(\[URL\])(.[^\[]*)(\[\/URL\])", RegexOptions.IgnoreCase);
  713. ubbStr = my.Replace(ubbStr, @"<A HREF=""http://$2"" TARGET=_blank>$2</A>");
  714. my = new Regex(@"(\[URL=(http:\/\/.[^\[]*)\])(.[^\[]*)(\[\/URL\])", RegexOptions.IgnoreCase);
  715. ubbStr = my.Replace(ubbStr, @"<A HREF=""$2"" TARGET=_blank>$3</A>");
  716. my = new Regex(@"(\[URL=(.[^\[]*)\])(.[^\[]*)(\[\/URL\])", RegexOptions.IgnoreCase);
  717. ubbStr = my.Replace(ubbStr, @"<A HREF=""http://$2"" TARGET=_blank>$3</A>");
  718. my = new Regex(@"(\[EMAIL\])(\S+\@.[^\[]*)(\[\/EMAIL\])", RegexOptions.IgnoreCase);
  719. ubbStr = my.Replace(ubbStr, @"<A HREF=""mailto:$2"">$2</A>");
  720. my = new Regex(@"(\[EMAIL=(\S+\@.[^\[]*)\])(.[^\[]*)(\[\/EMAIL\])", RegexOptions.IgnoreCase);
  721. ubbStr = my.Replace(ubbStr, @"<A HREF=""mailto:$2"" TARGET=_blank>$3</A>");
  722. my = new Regex(@"^(HTTP://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)", RegexOptions.IgnoreCase);
  723. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  724. my = new Regex(@"(HTTP://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)$", RegexOptions.IgnoreCase);
  725. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  726. my = new Regex(@"[^>=""](HTTP://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)", RegexOptions.IgnoreCase);
  727. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  728. my = new Regex(@"^(FTP://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)", RegexOptions.IgnoreCase);
  729. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  730. my = new Regex(@"(FTP://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)$", RegexOptions.IgnoreCase);
  731. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  732. my = new Regex(@"[^>=""](FTP://[A-Za-z0-9\.\/=\?%\-&_~`@':+!]+)", RegexOptions.IgnoreCase);
  733. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  734. my = new Regex(@"^(RTSP://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)", RegexOptions.IgnoreCase);
  735. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  736. my = new Regex(@"(RTSP://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)$", RegexOptions.IgnoreCase);
  737. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  738. my = new Regex(@"[^>=""](RTSP://[A-Za-z0-9\.\/=\?%\-&_~`@':+!]+)", RegexOptions.IgnoreCase);
  739. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  740. my = new Regex(@"^(MMS://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)", RegexOptions.IgnoreCase);
  741. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  742. my = new Regex(@"(MMS://[A-Za-z0-9\./=\?%\-&_~`@':+!]+)$", RegexOptions.IgnoreCase);
  743. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  744. my = new Regex(@"[^>=""](MMS://[A-Za-z0-9\.\/=\?%\-&_~`@':+!]+)", RegexOptions.IgnoreCase);
  745. ubbStr = my.Replace(ubbStr, @"<a target=_blank href=$1>$1</a>");
  746. my = new Regex(@"(\[HTML\])(.[^\[]*)(\[\/HTML\])", RegexOptions.IgnoreCase);
  747. ubbStr = my.Replace(ubbStr, @"<table width='100%' border='0' cellspacing='0' cellpadding='6' bgcolor=''><td><b>以下内容为程序代码:</b><br>$2</td></table>");
  748. my = new Regex(@"(\[CODE\])(.[^\[]*)(\[\/CODE\])", RegexOptions.IgnoreCase);
  749. ubbStr = my.Replace(ubbStr, @"<table width='100%' border='0' cellspacing='0' cellpadding='6' bgcolor=''><td><b>以下内容为程序代码:</b><br>$2</td></table>");
  750. my = new Regex(@"(\[COLOR=(.[^\[]*)\])(.[^\[]*)(\[\/COLOR\])", RegexOptions.IgnoreCase);
  751. ubbStr = my.Replace(ubbStr, @"<font COLOR=$2>$3</font>");
  752. my = new Regex(@"(\[FACE=(.[^\[]*)\])(.[^\[]*)(\[\/FACE\])", RegexOptions.IgnoreCase);
  753. ubbStr = my.Replace(ubbStr, @"<font FACE=$2>$3</font>");
  754. my = new Regex(@"(\[ALIGN=(.[^\[]*)\])(.*)(\[\/ALIGN\])", RegexOptions.IgnoreCase);
  755. ubbStr = my.Replace(ubbStr, @"<div ALIGN=$2>$3</div>");
  756. my = new Regex(@"(\[QUOTE\])(.*)(\[\/QUOTE\])", RegexOptions.IgnoreCase);
  757. ubbStr = my.Replace(ubbStr, @"<table cellpadding=0 cellspacing=0 border=0 WIDTH=94% bgcolor=#000000 align=center><tr><td><table width=100% cellpadding=5 cellspacing=1 border=0><TR><TD BGCOLOR=''>$2</table></table><br>");
  758. my = new Regex(@"(\[MOVE\])(.*)(\[\/MOVE\])", RegexOptions.IgnoreCase);
  759. ubbStr = my.Replace(ubbStr, @"<MARQUEE scrollamount=3>$2</marquee>");
  760. my = new Regex(@"\[GLOW=*([0-9]*),*(#*[a-z0-9]*),*([0-9]*)\](.[^\[]*)\[\/GLOW]", RegexOptions.IgnoreCase);
  761. ubbStr = my.Replace(ubbStr, @"<table width=$1 style=""filter:glow(color=$2, strength=$3)"">$4</table>");
  762. my = new Regex(@"\[SHADOW=*([0-9]*),*(#*[a-z0-9]*),*([0-9]*)\](.[^\[]*)\[\/SHADOW]", RegexOptions.IgnoreCase);
  763. ubbStr = my.Replace(ubbStr, @"<table width=$1 style=""filter:shadow(color=$2, strength=$3)"">$4</table>");
  764. my = new Regex(@"(\[I\])(.[^\[]*)(\[\/I\])", RegexOptions.IgnoreCase);
  765. ubbStr = my.Replace(ubbStr, @"<i>$2</i>");
  766. my = new Regex(@"(\[B\])(.[^\[]*)(\[\/U\])", RegexOptions.IgnoreCase);
  767. ubbStr = my.Replace(ubbStr, @"<u>$2</u>");
  768. my = new Regex(@"(\[B\])(.[^\[]*)(\[\/B\])", RegexOptions.IgnoreCase);
  769. ubbStr = my.Replace(ubbStr, @"<b>$2</b>");
  770. my = new Regex(@"(\[FLY\])(.[^\[]*)(\[\/FLY\])", RegexOptions.IgnoreCase);
  771. ubbStr = my.Replace(ubbStr, @"<marquee onmouseover='this.stop();' onmouseout='this.start();'>$2</marquee>");
  772. my = new Regex(@"(\[SIZE=1\])(.[^\[]*)(\[\/SIZE\])", RegexOptions.IgnoreCase);
  773. ubbStr = my.Replace(ubbStr, @"<font size=1>$2</font>");
  774. my = new Regex(@"(\[SIZE=2\])(.[^\[]*)(\[\/SIZE\])", RegexOptions.IgnoreCase);
  775. ubbStr = my.Replace(ubbStr, @"<font size=2>$2</font>");
  776. my = new Regex(@"(\[SIZE=3\])(.[^\[]*)(\[\/SIZE\])", RegexOptions.IgnoreCase);
  777. ubbStr = my.Replace(ubbStr, @"<font size=3>$2</font>");
  778. my = new Regex(@"(\[SIZE=4\])(.[^\[]*)(\[\/SIZE\])", RegexOptions.IgnoreCase);
  779. ubbStr = my.Replace(ubbStr, @"<font size=4>$2</font>");
  780. my = new Regex(@"(\[CENTER\])(.[^\[]*)(\[\/CENTER\])", RegexOptions.IgnoreCase);
  781. ubbStr = my.Replace(ubbStr, @"<center>$2</center>");
  782. return ubbStr;
  783. }
  784. /// <summary>
  785. /// UBB转HTML方式2
  786. /// </summary>
  787. /// <param name="ubbStr">UBB 代码</param>
  788. /// <returns>HTML代码</returns>
  789. public static async Task<string> UbbToHtml2Async(this string ubbStr) => await Task.Run(() => UbbToHtml2(ubbStr));
  790. /// <summary>
  791. /// Html转UBB
  792. /// </summary>
  793. /// <param name="chr">HTML代码</param>
  794. /// <returns>UBB代码</returns>
  795. public static string HtmltoUBB(this string chr)
  796. {
  797. if (chr == null) return "";
  798. chr = chr.Replace("&lt", "<");
  799. chr = chr.Replace("&gt", ">");
  800. chr = chr.Replace("<br/>", " ");
  801. chr = Regex.Replace(chr, @"<a href=$1 target=_blank>$2</a>", @"[url=(?<x>[^]]*)](?<y>[^]]*)[/url]", RegexOptions.IgnoreCase);
  802. chr = Regex.Replace(chr, @"<a href=$1 target=_blank>$1</a>", @"[url](?<x>[^]]*)[/url]", RegexOptions.IgnoreCase);
  803. chr = Regex.Replace(chr, @"<a href=$1>$2</a>", @"[email=(?<x>[^]]*)](?<y>[^]]*)[/email]", RegexOptions.IgnoreCase);
  804. chr = Regex.Replace(chr, @"<a href=$1>$1</a>", @"[email](?<x>[^]]*)[/email]", RegexOptions.IgnoreCase);
  805. chr = Regex.Replace(chr, @"<OBJECT codeBase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=4,0,2,0 classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 width=500 height=400><PARAM NAME=movie VALUE=""$1""><PARAM NAME=quality VALUE=high><embed src=""$1"" quality=high pluginspage='http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash' type='application/x-shockwave-flash' width=500 height=400>$1</embed></OBJECT>", @"[flash](?<x>[^]]*)[/flash]", RegexOptions.IgnoreCase);
  806. chr = Regex.Replace(chr, @"<IMG SRC=""$1"" border=0>", @"[img](?<x>[^]]*)[/img]", RegexOptions.IgnoreCase);
  807. chr = Regex.Replace(chr, @"<font color=$1>$2</font>", @"[color=(?<x>[^]]*)](?<y>[^]]*)[/color]", RegexOptions.IgnoreCase);
  808. chr = Regex.Replace(chr, @"<font face=$1>$2</font>", @"[face=(?<x>[^]]*)](?<y>[^]]*)[/face]", RegexOptions.IgnoreCase);
  809. chr = Regex.Replace(chr, @"<font size=1>$1</font>", @"[size=1](?<x>[^]]*)[/size]", RegexOptions.IgnoreCase);
  810. chr = Regex.Replace(chr, @"<font size=2>$1</font>", @"[size=2](?<x>[^]]*)[/size]", RegexOptions.IgnoreCase);
  811. chr = Regex.Replace(chr, @"<font size=3>$1</font>", @"[size=3](?<x>[^]]*)[/size]", RegexOptions.IgnoreCase);
  812. chr = Regex.Replace(chr, @"<font size=4>$1</font>", @"[size=4](?<x>[^]]*)[/size]", RegexOptions.IgnoreCase);
  813. chr = Regex.Replace(chr, @"<align=$1>$2</align>", @"[align=(?<x>[^]]*)](?<y>[^]]*)[/align]", RegexOptions.IgnoreCase);
  814. chr = Regex.Replace(chr, @"<marquee width=90% behavior=alternate scrollamount=3>$1</marquee>", @"[fly](?<x>[^]]*)[/fly]", RegexOptions.IgnoreCase);
  815. chr = Regex.Replace(chr, @"<marquee scrollamount=3>$1</marquee>", @"[move](?<x>[^]]*)[/move]", RegexOptions.IgnoreCase);
  816. chr = Regex.Replace(chr, @"<table width=$1 style='filter:glow(color=$2, strength=$3)'>$4</table>", @"[glow=(?<x>[^]]*),(?<y>[^]]*),(?<z>[^]]*)](?<w>[^]]*)[/glow]", RegexOptions.IgnoreCase);
  817. chr = Regex.Replace(chr, @"<table width=$1 style='filter:shadow(color=$2, strength=$3)'>$4</table>", @"[shadow=(?<x>[^]]*),(?<y>[^]]*),(?<z>[^]]*)](?<w>[^]]*)[/shadow]", RegexOptions.IgnoreCase);
  818. chr = Regex.Replace(chr, @"<b>$1</b>", @"[b](?<x>[^]]*)[/b]", RegexOptions.IgnoreCase);
  819. chr = Regex.Replace(chr, @"<i>$1</i>", @"[i](?<x>[^]]*)[/i]", RegexOptions.IgnoreCase);
  820. chr = Regex.Replace(chr, @"<u>$1</u>", @"[u](?<x>[^]]*)[/u]", RegexOptions.IgnoreCase);
  821. chr = Regex.Replace(chr, @"<pre id=code><font size=1 face='Verdana, Arial' id=code>$1</font id=code></pre id=code>", @"[code](?<x>[^]]*)[/code]", RegexOptions.IgnoreCase);
  822. chr = Regex.Replace(chr, @"<ul>$1</ul>", @"[list](?<x>[^]]*)[/list]", RegexOptions.IgnoreCase);
  823. chr = Regex.Replace(chr, @"<ol type=1>$1</ol id=1>", @"[list=1](?<x>[^]]*)[/list]", RegexOptions.IgnoreCase);
  824. chr = Regex.Replace(chr, @"<ol type=a>$1</ol id=a>", @"[list=a](?<x>[^]]*)[/list]", RegexOptions.IgnoreCase);
  825. chr = Regex.Replace(chr, @"<li>$1</li>", @"[*](?<x>[^]]*)[/*]", RegexOptions.IgnoreCase);
  826. chr = Regex.Replace(chr, @"<center>—— 以下是引用 ——<table border='1' width='80%' cellpadding='10' cellspacing='0' ><tr><td>$1</td></tr></table></center>", @"[quote](?<x>.*)[/quote]", RegexOptions.IgnoreCase);
  827. return chr;
  828. }
  829. /// <summary>
  830. /// Html转UBB
  831. /// </summary>
  832. /// <param name="chr">HTML代码</param>
  833. /// <returns>UBB代码</returns>
  834. public static async Task<string> HtmltoUBBAsync(this string chr) => await Task.Run(() => HtmltoUBB(chr));
  835. #endregion
  836. #region 数字互转
  837. /// <summary>
  838. /// 字符串转int
  839. /// </summary>
  840. /// <param name="s">源字符串</param>
  841. /// <returns>int类型的数字</returns>
  842. public static int ToInt32(this string s)
  843. {
  844. try
  845. {
  846. return Convert.ToInt32(s);
  847. }
  848. catch
  849. {
  850. return 0;
  851. }
  852. }
  853. /// <summary>
  854. /// 字符串转long
  855. /// </summary>
  856. /// <param name="s">源字符串</param>
  857. /// <returns>int类型的数字</returns>
  858. public static long ToInt64(this string s)
  859. {
  860. try
  861. {
  862. return Convert.ToInt64(s);
  863. }
  864. catch
  865. {
  866. return 0;
  867. }
  868. }
  869. /// <summary>
  870. /// 字符串转double
  871. /// </summary>
  872. /// <param name="s">源字符串</param>
  873. /// <returns>double类型的数据</returns>
  874. public static double ToDouble(this string s)
  875. {
  876. try
  877. {
  878. return Convert.ToDouble(s);
  879. }
  880. catch
  881. {
  882. return 0;
  883. }
  884. }
  885. /// <summary>
  886. /// 字符串转decimal
  887. /// </summary>
  888. /// <param name="s">源字符串</param>
  889. /// <returns>int类型的数字</returns>
  890. public static decimal ToDecimal(this string s)
  891. {
  892. try
  893. {
  894. return Convert.ToDecimal(s);
  895. }
  896. catch
  897. {
  898. return 0;
  899. }
  900. }
  901. /// <summary>
  902. /// 字符串转decimal
  903. /// </summary>
  904. /// <param name="s">源字符串</param>
  905. /// <returns>int类型的数字</returns>
  906. public static decimal ToDecimal(this double s)
  907. {
  908. try
  909. {
  910. return Convert.ToDecimal(s);
  911. }
  912. catch
  913. {
  914. return 0;
  915. }
  916. }
  917. /// <summary>
  918. /// 字符串转double
  919. /// </summary>
  920. /// <param name="s">源字符串</param>
  921. /// <returns>double类型的数据</returns>
  922. public static double ToDouble(this decimal s)
  923. {
  924. try
  925. {
  926. return Convert.ToDouble(s);
  927. }
  928. catch
  929. {
  930. return 0;
  931. }
  932. }
  933. /// <summary>
  934. /// 将double转换成int
  935. /// </summary>
  936. /// <param name="num">double类型</param>
  937. /// <returns>int类型</returns>
  938. public static int ToInt32(this double num)
  939. {
  940. return (int)Math.Floor(num);
  941. }
  942. /// <summary>
  943. /// 将double转换成int
  944. /// </summary>
  945. /// <param name="num">double类型</param>
  946. /// <returns>int类型</returns>
  947. public static int ToInt32(this decimal num)
  948. {
  949. return (int)Math.Floor(num);
  950. }
  951. /// <summary>
  952. /// 将int转换成double
  953. /// </summary>
  954. /// <param name="num">int类型</param>
  955. /// <returns>int类型</returns>
  956. public static double ToDouble(this int num)
  957. {
  958. return num * 1.0;
  959. }
  960. /// <summary>
  961. /// 将int转换成decimal
  962. /// </summary>
  963. /// <param name="num">int类型</param>
  964. /// <returns>int类型</returns>
  965. public static decimal ToDecimal(this int num)
  966. {
  967. return (decimal)(num * 1.0);
  968. }
  969. #endregion
  970. #region 检测字符串中是否包含列表中的关键词
  971. /// <summary>
  972. /// 检测字符串中是否包含列表中的关键词
  973. /// </summary>
  974. /// <param name="s">源字符串</param>
  975. /// <param name="keys">关键词列表</param>
  976. /// <returns></returns>
  977. public static bool Contains(this string s, string[] keys) => Regex.IsMatch(s.ToLower(), string.Join("|", keys).ToLower());
  978. #endregion
  979. #region 匹配Email
  980. /// <summary>
  981. /// 匹配Email
  982. /// </summary>
  983. /// <param name="s">源字符串</param>
  984. /// <param name="isMatch">是否匹配成功,若返回true,则会得到一个Match对象,否则为null</param>
  985. /// <returns>匹配对象</returns>
  986. public static Match MatchEmail(this string s, out bool isMatch)
  987. {
  988. Match match = Regex.Match(s, @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
  989. isMatch = match.Success;
  990. return isMatch ? match : null;
  991. }
  992. /// <summary>
  993. /// 匹配Email
  994. /// </summary>
  995. /// <param name="s">源字符串</param>
  996. /// <returns>是否匹配成功</returns>
  997. public static bool MatchEmail(this string s)
  998. {
  999. MatchEmail(s, out bool success);
  1000. return success;
  1001. }
  1002. #endregion
  1003. #region 匹配完整的URL
  1004. /// <summary>
  1005. /// 匹配完整格式的URL,支持以下格式的URL,支持中文域名:<br/>
  1006. /// 支持不带协议名的网址,支持自适应协议的网址,支持完整路径,支持查询参数,支持锚点,支持锚点查询参数,支持16进制编码<br/>
  1007. /// www.baidu.com <br/>
  1008. /// www.baidu.com <br/>
  1009. /// baidu.com <br/>
  1010. /// //www.baidu.com <br/>
  1011. /// http://www.baidu.com <br/>
  1012. /// https://www.baidu.com <br/>
  1013. /// https://baidu.com <br/>
  1014. /// ftp://baidu.com <br/>
  1015. /// ftp://baidu.com/abc/def <br/>
  1016. /// ftp://admin:[email protected] <br/>
  1017. /// ftp://admin:[email protected]/abc/def <br/>
  1018. /// https://baidu.com:8080 <br/>
  1019. /// https://baidu.com/abc/def <br/>
  1020. /// https://baidu.com:8080/abc/def <br/>
  1021. /// https://baidu.com:8080/abc/def/hhh.html <br/>
  1022. /// https://baidu.com:8080/abc/def/hhh.html?s=www <br/>
  1023. /// https://baidu.com/abc/def/hhh.html?s=w@w{w}!s <br/>
  1024. /// https://baidu.com:8080/abc/def/hhh.html?s=www&amp;x=yy+y <br/>
  1025. /// https://baidu.com/abc/def/hhh.html?s=www&amp;x=yyy <br/>
  1026. /// https://baidu.com:8080/abc/def/hhh.html?s=www&amp;x=yyy#top <br/>
  1027. /// https://baidu.com:8080/abc/def/hi_jk-mn%ADF%AA/hhh.html?s=www&amp;x=yyy#top <br/>
  1028. /// https://baidu.com:8080/abc/def/hi_j+k-mn%ADF%AA?s=www&amp;x=yyy#top/aaa <br/>
  1029. /// https://baidu.com:8080/abc/def/hi_jk-mn%ADF%AA?s=www&amp;x=yyy#top/aaa/bbb/ccc <br/>
  1030. /// http://music.163.com/#/my/m/music/empty <br/>
  1031. /// http://music.163.com/abc/#/my/m/music/empty <br/>
  1032. /// http://music.163.com/def/hhh.html?s=www&amp;x=yyy#/my/m/music/empty <br/>
  1033. /// http://music.163.com/def/hhh.html?s=www&amp;x=yyy/#/my/m/music/empty <br/>
  1034. /// http://music.163.com/#/search/m/?%23%2Fmy%2Fm%2Fmusic%2Fempty=&amp;s=fade&amp;type=1!k <br/>
  1035. /// </summary>
  1036. /// <param name="s">源字符串</param>
  1037. /// <param name="isMatch">是否匹配成功,若返回true,则会得到一个Match对象,否则为null</param>
  1038. /// <returns>匹配对象</returns>
  1039. public static Match MatchUrl(this string s, out bool isMatch)
  1040. {
  1041. Match match = Regex.Match(s, @"^((\w*):?//)?((\w+)\.|((\S+):(\S+))@)?((\w+)\.(\w+))(:(\d{1,5}))?(/([a-z0-9A-Z-_@{}!+%/]+(\.\w+)?)?(\?([a-z0-9A-Z-_@{}!+%]+=[a-z0-9A-Z-_@{}!+%]+&?)+)?(/?#[a-z0-9A-Z-_@{}!+%/]+)?(\?([a-z0-9A-Z-_@{}!+%]+=[a-z0-9A-Z-_@{}!+%]*&?)+)?)?$");
  1042. isMatch = match.Success;
  1043. return isMatch ? match : null;
  1044. }
  1045. /// <summary>
  1046. /// 匹配完整格式的URL,支持以下格式的URL,支持中文域名:<br/>
  1047. /// 支持不带协议名的网址,支持自适应协议的网址,支持完整路径,支持查询参数,支持锚点,支持锚点查询参数,支持16进制编码<br/>
  1048. /// www.baidu.com <br/>
  1049. /// www.baidu.com <br/>
  1050. /// baidu.com <br/>
  1051. /// //www.baidu.com <br/>
  1052. /// http://www.baidu.com <br/>
  1053. /// https://www.baidu.com <br/>
  1054. /// https://baidu.com <br/>
  1055. /// ftp://baidu.com <br/>
  1056. /// ftp://baidu.com/abc/def <br/>
  1057. /// ftp://admin:[email protected] <br/>
  1058. /// ftp://admin:[email protected]/abc/def <br/>
  1059. /// https://baidu.com:8080 <br/>
  1060. /// https://baidu.com/abc/def <br/>
  1061. /// https://baidu.com:8080/abc/def <br/>
  1062. /// https://baidu.com:8080/abc/def/hhh.html <br/>
  1063. /// https://baidu.com:8080/abc/def/hhh.html?s=www <br/>
  1064. /// https://baidu.com/abc/def/hhh.html?s=w@w{w}!s <br/>
  1065. /// https://baidu.com:8080/abc/def/hhh.html?s=www&amp;x=yy+y <br/>
  1066. /// https://baidu.com/abc/def/hhh.html?s=www&amp;x=yyy <br/>
  1067. /// https://baidu.com:8080/abc/def/hhh.html?s=www&amp;x=yyy#top <br/>
  1068. /// https://baidu.com:8080/abc/def/hi_jk-mn%ADF%AA/hhh.html?s=www&amp;x=yyy#top <br/>
  1069. /// https://baidu.com:8080/abc/def/hi_j+k-mn%ADF%AA?s=www&amp;x=yyy#top/aaa <br/>
  1070. /// https://baidu.com:8080/abc/def/hi_jk-mn%ADF%AA?s=www&amp;x=yyy#top/aaa/bbb/ccc <br/>
  1071. /// http://music.163.com/#/my/m/music/empty <br/>
  1072. /// http://music.163.com/abc/#/my/m/music/empty <br/>
  1073. /// http://music.163.com/def/hhh.html?s=www&amp;x=yyy#/my/m/music/empty <br/>
  1074. /// http://music.163.com/def/hhh.html?s=www&amp;x=yyy/#/my/m/music/empty <br/>
  1075. /// http://music.163.com/#/search/m/?%23%2Fmy%2Fm%2Fmusic%2Fempty=&amp;s=fade&amp;type=1!k <br/>
  1076. /// </summary>
  1077. /// <param name="s">源字符串</param>
  1078. /// <returns>是否匹配成功</returns>
  1079. public static bool MatchUrl(this string s)
  1080. {
  1081. MatchUrl(s, out bool success);
  1082. return success;
  1083. }
  1084. #endregion
  1085. #region 权威校验身份证号码
  1086. /// <summary>
  1087. /// 根据GB11643-1999标准权威校验中国身份证号码的合法性
  1088. /// </summary>
  1089. /// <param name="s">源字符串</param>
  1090. /// <returns>是否匹配成功</returns>
  1091. public static bool MatchIdentifyCard(this string s)
  1092. {
  1093. if (s.Length == 18)
  1094. {
  1095. long n;
  1096. if (long.TryParse(s.Remove(17), out n) == false || n < Math.Pow(10, 16) || long.TryParse(s.Replace('x', '0').Replace('X', '0'), out n) == false)
  1097. {
  1098. return false; //数字验证
  1099. }
  1100. string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
  1101. if (address.IndexOf(s.Remove(2), StringComparison.Ordinal) == -1)
  1102. {
  1103. return false; //省份验证
  1104. }
  1105. string birth = s.Substring(6, 8).Insert(6, "-").Insert(4, "-");
  1106. DateTime time;
  1107. if (!DateTime.TryParse(birth, out time))
  1108. {
  1109. return false; //生日验证
  1110. }
  1111. string[] arrVarifyCode = ("1,0,x,9,8,7,6,5,4,3,2").Split(',');
  1112. string[] wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(',');
  1113. char[] ai = s.Remove(17).ToCharArray();
  1114. int sum = 0;
  1115. for (int i = 0; i < 17; i++)
  1116. {
  1117. sum += wi[i].ToInt32() * ai[i].ToString().ToInt32();
  1118. }
  1119. int y;
  1120. Math.DivRem(sum, 11, out y);
  1121. if (arrVarifyCode[y] != s.Substring(17, 1).ToLower())
  1122. {
  1123. return false; //校验码验证
  1124. }
  1125. return true; //符合GB11643-1999标准
  1126. }
  1127. if (s.Length == 15)
  1128. {
  1129. long n;
  1130. if (long.TryParse(s, out n) == false || n < Math.Pow(10, 14))
  1131. {
  1132. return false; //数字验证
  1133. }
  1134. string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
  1135. if (address.IndexOf(s.Remove(2), StringComparison.Ordinal) == -1)
  1136. {
  1137. return false; //省份验证
  1138. }
  1139. string birth = s.Substring(6, 6).Insert(4, "-").Insert(2, "-");
  1140. DateTime time;
  1141. if (DateTime.TryParse(birth, out time) == false)
  1142. {
  1143. return false; //生日验证
  1144. }
  1145. return true;
  1146. }
  1147. return false;
  1148. }
  1149. #endregion
  1150. #region 校验IP地址的合法性
  1151. /// <summary>
  1152. /// 校验IP地址的正确性,同时支持IPv4和IPv6
  1153. /// </summary>
  1154. /// <param name="s">源字符串</param>
  1155. /// <param name="isMatch">是否匹配成功,若返回true,则会得到一个Match对象,否则为null</param>
  1156. /// <returns>匹配对象</returns>
  1157. public static Match MatchInetAddress(this string s, out bool isMatch)
  1158. {
  1159. Match match;
  1160. if (s.Contains(":"))
  1161. {
  1162. //IPv6
  1163. match = Regex.Match(s, "^((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))$");
  1164. isMatch = match.Success;
  1165. }
  1166. else
  1167. {
  1168. //IPv4
  1169. match = Regex.Match(s, @"^(\d+)\.(\d+)\.(\d+)\.(\d+)$");
  1170. isMatch = match.Success;
  1171. foreach (Group m in match.Groups)
  1172. {
  1173. if (m.Value.ToInt32() < 0 || m.Value.ToInt32() > 255)
  1174. {
  1175. isMatch = false;
  1176. break;
  1177. }
  1178. }
  1179. }
  1180. return isMatch ? match : null;
  1181. }
  1182. /// <summary>
  1183. /// 校验IP地址的正确性,同时支持IPv4和IPv6
  1184. /// </summary>
  1185. /// <param name="s">源字符串</param>
  1186. /// <returns>是否匹配成功</returns>
  1187. public static bool MatchInetAddress(this string s)
  1188. {
  1189. MatchInetAddress(s, out bool success);
  1190. return success;
  1191. }
  1192. #endregion
  1193. #region 校验手机号码的正确性
  1194. /// <summary>
  1195. /// 匹配手机号码
  1196. /// </summary>
  1197. /// <param name="s">源字符串</param>
  1198. /// <param name="isMatch">是否匹配成功,若返回true,则会得到一个Match对象,否则为null</param>
  1199. /// <returns>匹配对象</returns>
  1200. public static Match MatchPhoneNumber(this string s, out bool isMatch)
  1201. {
  1202. Match match = Regex.Match(s, @"^((1[3,5,8][0-9])|(14[5,7])|(17[0,1,3,6,7,8])|(19[8,9]))\d{8}$");
  1203. isMatch = match.Success;
  1204. return isMatch ? match : null;
  1205. }
  1206. /// <summary>
  1207. /// 匹配手机号码
  1208. /// </summary>
  1209. /// <param name="s">源字符串</param>
  1210. /// <returns>是否匹配成功</returns>
  1211. public static bool MatchPhoneNumber(this string s)
  1212. {
  1213. MatchPhoneNumber(s, out bool success);
  1214. return success;
  1215. }
  1216. #endregion
  1217. /// <summary>
  1218. /// 严格比较两个对象是否是同一对象
  1219. /// </summary>
  1220. /// <param name="_this">自己</param>
  1221. /// <param name="o">需要比较的对象</param>
  1222. /// <returns>是否同一对象</returns>
  1223. public new static bool ReferenceEquals(this object _this, object o) => object.ReferenceEquals(_this, o);
  1224. /// <summary>
  1225. /// 判断字符串是否为空
  1226. /// </summary>
  1227. /// <param name="s"></param>
  1228. /// <returns></returns>
  1229. public static bool IsNullOrEmpty(this string s) => string.IsNullOrEmpty(s);
  1230. /// <summary>
  1231. /// 类型直转
  1232. /// </summary>
  1233. /// <typeparam name="T"></typeparam>
  1234. /// <param name="value"></param>
  1235. /// <returns></returns>
  1236. public static T To<T>(this IConvertible value)
  1237. {
  1238. try
  1239. {
  1240. return (T)Convert.ChangeType(value, typeof(T));
  1241. }
  1242. catch
  1243. {
  1244. return default(T);
  1245. }
  1246. }
  1247. /// <summary>
  1248. /// 字符串转时间
  1249. /// </summary>
  1250. /// <param name="value"></param>
  1251. /// <returns></returns>
  1252. public static DateTime ToDateTime(this string value)
  1253. {
  1254. try
  1255. {
  1256. return DateTime.Parse(value);
  1257. }
  1258. catch
  1259. {
  1260. return default(DateTime);
  1261. }
  1262. }
  1263. /// <summary>
  1264. /// 字符串转Guid
  1265. /// </summary>
  1266. /// <param name="s"></param>
  1267. /// <returns></returns>
  1268. public static Guid ToGuid(this string s)
  1269. {
  1270. return Guid.Parse(s);
  1271. }
  1272. /// <summary>
  1273. /// 根据正则替换
  1274. /// </summary>
  1275. /// <param name="input"></param>
  1276. /// <param name="regex">正则表达式</param>
  1277. /// <param name="replacement">新内容</param>
  1278. /// <returns></returns>
  1279. public static string Replace(this string input, Regex regex, string replacement)
  1280. {
  1281. return regex.Replace(input, replacement);
  1282. }
  1283. /// <summary>
  1284. /// 生成唯一短字符串
  1285. /// </summary>
  1286. /// <param name="str"></param>
  1287. /// <param name="length">生成的字符串长度,越长冲突的概率越小,默认长度为6,最小长度为5,最大长度为22</param>
  1288. /// <returns></returns>
  1289. public static string CreateShortToken(this string str, int length = 6)
  1290. {
  1291. var temp = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Trim('=');
  1292. if (length <= 22)
  1293. {
  1294. if (length < 5)
  1295. {
  1296. length = 5;
  1297. }
  1298. temp = temp.Substring(0, length);
  1299. }
  1300. return temp;
  1301. }
  1302. /// <summary>
  1303. /// 按字段去重
  1304. /// </summary>
  1305. /// <typeparam name="TSource"></typeparam>
  1306. /// <typeparam name="TKey"></typeparam>
  1307. /// <param name="source"></param>
  1308. /// <param name="keySelector"></param>
  1309. /// <returns></returns>
  1310. public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
  1311. {
  1312. HashSet<TKey> hash = new HashSet<TKey>();
  1313. return source.Where(p => hash.Add(keySelector(p)));
  1314. }
  1315. /// <summary>
  1316. /// 将小数截断为8位
  1317. /// </summary>
  1318. /// <param name="num"></param>
  1319. /// <returns></returns>
  1320. public static double Digits8(this double num)
  1321. {
  1322. return (long)(num * 1E+8) * 1e-8;
  1323. }
  1324. }
  1325. }