FRRandom.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. using System;
  2. using System.Text;
  3. using System.Data;
  4. using System.Globalization;
  5. using System.Collections.Generic;
  6. using FastReport.Data;
  7. namespace FastReport.Utils
  8. {
  9. /// <summary>
  10. /// The pseudo-random generator.
  11. /// </summary>
  12. public class FRRandom
  13. {
  14. #region Fields
  15. private readonly Random random;
  16. private static readonly char[] lowerLetters =
  17. {
  18. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
  19. 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
  20. };
  21. private static readonly char[] upperLetters =
  22. {
  23. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  24. 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
  25. };
  26. #endregion Fields
  27. #region Public Methods
  28. /// <summary>
  29. /// Gets a random letter in same case that source character.
  30. /// </summary>
  31. /// <param name="source">The source character.</param>
  32. /// <returns>The random character.</returns>
  33. public char NextLetter(char source)
  34. {
  35. if (char.IsLower(source))
  36. return lowerLetters[random.Next(lowerLetters.Length)];
  37. else if (char.IsUpper(source))
  38. return upperLetters[random.Next(upperLetters.Length)];
  39. return source;
  40. }
  41. /// <summary>
  42. /// Gets random int value from <b>0</b> to <b>9</b>.
  43. /// </summary>
  44. /// <returns>Random int value.</returns>
  45. public int NextDigit()
  46. {
  47. return random.Next(10);
  48. }
  49. /// <summary>
  50. /// Gets random int value from <b>0</b> to <b>max</b>.
  51. /// </summary>
  52. /// <param name="max">The maximum for random digit.</param>
  53. /// <returns>Random int value.</returns>
  54. public int NextDigit(int max)
  55. {
  56. return random.Next(max + 1);
  57. }
  58. /// <summary>
  59. /// Gets random int value from <b>min</b> to <b>max</b>.
  60. /// </summary>
  61. /// <param name="min">The minimum for random digit.</param>
  62. /// <param name="max">The maximum for random digit.</param>
  63. /// <returns>Random int value.</returns>
  64. public int NextDigit(int min, int max)
  65. {
  66. return random.Next(min, max + 1);
  67. }
  68. /// <summary>
  69. /// Gets number of random digits from <b>0</b> to <b>9</b>.
  70. /// </summary>
  71. /// <param name="number">The number of digits.</param>
  72. /// <returns>Number of random digits.</returns>
  73. public string NextDigits(int number)
  74. {
  75. if (number <= 0)
  76. return "";
  77. StringBuilder sb = new StringBuilder();
  78. for (int i = 0; i < number; i++)
  79. {
  80. sb.Append(NextDigit());
  81. }
  82. return sb.ToString();
  83. }
  84. /// <summary>
  85. /// Gets the random byte value.
  86. /// </summary>
  87. /// <returns>Random byte value.</returns>
  88. public byte NextByte()
  89. {
  90. return (byte)random.Next(byte.MaxValue);
  91. }
  92. /// <summary>
  93. /// Gets random byte array with specified number of elements.
  94. /// </summary>
  95. /// <param name="number">The number of elements in array.</param>
  96. /// <returns>Random byte array.</returns>
  97. public byte[] NextBytes(int number)
  98. {
  99. byte[] bytes = new byte[number];
  100. random.NextBytes(bytes);
  101. return bytes;
  102. }
  103. /// <summary>
  104. /// Gets the randomized char value.
  105. /// </summary>
  106. /// <returns>Random char value.</returns>
  107. public char NextChar()
  108. {
  109. return Convert.ToChar(random.Next(char.MaxValue));
  110. }
  111. /// <summary>
  112. /// Gets the random day from start to DataTime.Today.
  113. /// </summary>
  114. /// <param name="start">The starting DateTime value.</param>
  115. /// <returns>Random DateTime value.</returns>
  116. public DateTime NextDay(DateTime start)
  117. {
  118. if (start > DateTime.Today)
  119. return DateTime.Today;
  120. int range = (DateTime.Today - start).Days;
  121. return start.AddDays(random.Next(range));
  122. }
  123. /// <summary>
  124. /// Gets the randomized TimeSpan value beetwin specified hours.
  125. /// </summary>
  126. /// <param name="start">The starting hour (0 - 24).</param>
  127. /// <param name="end">The ending hour (0 - 24).</param>
  128. /// <returns>Random TimeSpan value.</returns>
  129. public TimeSpan NextTimeSpanBetweenHours(int start, int end)
  130. {
  131. if (start < 0)
  132. start = 0;
  133. if (end > 24)
  134. end = 24;
  135. if (start > end)
  136. {
  137. int temp = start;
  138. start = end;
  139. end = temp;
  140. }
  141. TimeSpan startTs = TimeSpan.FromHours(start);
  142. TimeSpan endTs = TimeSpan.FromHours(end);
  143. int maxMinutes = (int)(endTs - startTs).TotalMinutes;
  144. int randomMinutes = random.Next(maxMinutes);
  145. TimeSpan result = startTs.Add(TimeSpan.FromMinutes(randomMinutes));
  146. return result;
  147. }
  148. /// <summary>
  149. /// Gets the randomized decimal value with same number of digits that in source value.
  150. /// </summary>
  151. /// <param name="source">The source decimal value.</param>
  152. /// <returns>Random decimal value based on source.</returns>
  153. public decimal RandomizeDecimal(decimal source)
  154. {
  155. StringBuilder sb = new StringBuilder();
  156. string[] parts = source.ToString(CultureInfo.InvariantCulture).ToUpper().Split('E');
  157. string e = "";
  158. if (parts.Length > 1)
  159. e = "E" + parts[1];
  160. parts = parts[0].Split('.');
  161. if (parts.Length > 0)
  162. {
  163. int length = parts[0].Length;
  164. if (source < 0.0m)
  165. {
  166. sb.Append("-");
  167. length--;
  168. }
  169. sb.Append(NextDigit(1, 9));
  170. sb.Append(NextDigits(length - 1));
  171. }
  172. if (parts.Length > 1)
  173. {
  174. sb.Append(".");
  175. sb.Append(NextDigits(parts[1].Length - 1));
  176. sb.Append(NextDigit(1, 9));
  177. }
  178. sb.Append(e);
  179. decimal result;
  180. bool parsed = decimal.TryParse(sb.ToString(), NumberStyles.Float,
  181. CultureInfo.InvariantCulture, out result);
  182. if (parsed)
  183. return result;
  184. return source;
  185. }
  186. /// <summary>
  187. /// Gets the randomized double value with same number of digits that in source value.
  188. /// </summary>
  189. /// <param name="source">The source double value.</param>
  190. /// <returns>Random double value based on source.</returns>
  191. public double RandomizeDouble(double source)
  192. {
  193. return (double)RandomizeDecimal((decimal)source);
  194. }
  195. /// <summary>
  196. /// Gets the randomized Int16 value with same number of digits that in source value.
  197. /// </summary>
  198. /// <param name="source">The source Int16 value.</param>
  199. /// <returns>Random Int16 value based on source.</returns>
  200. public Int16 RandomizeInt16(Int16 source)
  201. {
  202. StringBuilder sb = new StringBuilder();
  203. int length = source.ToString(CultureInfo.InvariantCulture).Length;
  204. if (source < 0)
  205. {
  206. sb.Append('-');
  207. length--;
  208. }
  209. int maxLength = Int16.MaxValue.ToString(CultureInfo.InvariantCulture).Length;
  210. if (length < maxLength)
  211. {
  212. sb.Append(NextDigit(1, 9));
  213. sb.Append(NextDigits(length - 1));
  214. }
  215. else // Guarantee a value less than 32 000.
  216. {
  217. int next = NextDigit(1, 3);
  218. sb.Append(next);
  219. if (next < 3)
  220. sb.Append(NextDigits(maxLength - 1));
  221. else
  222. {
  223. sb.Append(NextDigit(1));
  224. sb.Append(NextDigits(maxLength - 2));
  225. }
  226. }
  227. Int16 result;
  228. bool parsed = Int16.TryParse(sb.ToString(), out result);
  229. if (parsed)
  230. return result;
  231. return source;
  232. }
  233. /// <summary>
  234. /// Gets the randomized Int32 value with same number of digits that in source value.
  235. /// </summary>
  236. /// <param name="source">The source Int32 value.</param>
  237. /// <returns>Random Int32 value based on source.</returns>
  238. public Int32 RandomizeInt32(Int32 source)
  239. {
  240. StringBuilder sb = new StringBuilder();
  241. int length = source.ToString(CultureInfo.InvariantCulture).Length;
  242. if (source < 0)
  243. {
  244. sb.Append('-');
  245. length--;
  246. }
  247. int maxLength = Int32.MaxValue.ToString(CultureInfo.InvariantCulture).Length;
  248. if (length < maxLength)
  249. {
  250. sb.Append(NextDigit(1, 9));
  251. sb.Append(NextDigits(length - 1));
  252. }
  253. else // Guarantee a value less than 2 200 000 000.
  254. {
  255. int next = NextDigit(1, 2);
  256. sb.Append(next);
  257. if (next < 2)
  258. sb.Append(NextDigits(maxLength - 1));
  259. else
  260. {
  261. sb.Append(NextDigit(1));
  262. sb.Append(NextDigits(maxLength - 2));
  263. }
  264. }
  265. Int32 result;
  266. bool parsed = Int32.TryParse(sb.ToString(), out result);
  267. if (parsed)
  268. return result;
  269. return source;
  270. }
  271. /// <summary>
  272. /// Gets the randomized Int64 value with same number of digits that in source value.
  273. /// </summary>
  274. /// <param name="source">The source Int64 value.</param>
  275. /// <returns>Random Int64 value based on source.</returns>
  276. public Int64 RandomizeInt64(Int64 source)
  277. {
  278. StringBuilder sb = new StringBuilder();
  279. int length = source.ToString(CultureInfo.InvariantCulture).Length;
  280. if (source < 0)
  281. {
  282. sb.Append('-');
  283. length--;
  284. }
  285. int maxLength = Int64.MaxValue.ToString(CultureInfo.InvariantCulture).Length;
  286. if (length < maxLength)
  287. {
  288. sb.Append(NextDigit(1, 9));
  289. sb.Append(NextDigits(length - 1));
  290. }
  291. else // Guarantee a value less than 9 200 000 000 000 000 000.
  292. {
  293. int next = NextDigit(1, 9);
  294. sb.Append(next);
  295. if (next < 9)
  296. sb.Append(NextDigits(maxLength - 1));
  297. else
  298. {
  299. sb.Append(NextDigit(1));
  300. sb.Append(NextDigits(maxLength - 2));
  301. }
  302. }
  303. Int64 result;
  304. bool parsed = Int64.TryParse(sb.ToString(), out result);
  305. if (parsed)
  306. return result;
  307. return source;
  308. }
  309. /// <summary>
  310. /// Gets the randomized SByte value with same number of digits that in source value.
  311. /// </summary>
  312. /// <param name="source">The source SByte value.</param>
  313. /// <returns>Random SByte value based on source.</returns>
  314. public SByte RandomizeSByte(SByte source)
  315. {
  316. StringBuilder sb = new StringBuilder();
  317. int length = source.ToString(CultureInfo.InvariantCulture).Length;
  318. if (source < 0)
  319. {
  320. sb.Append('-');
  321. length--;
  322. }
  323. int maxLength = SByte.MaxValue.ToString(CultureInfo.InvariantCulture).Length;
  324. if (length < maxLength)
  325. sb.Append(NextDigits(length));
  326. else // Guarantee a value less than 128.
  327. {
  328. int next = NextDigit(1);
  329. sb.Append(next);
  330. if (next < 1)
  331. sb.Append(NextDigits(maxLength - 1));
  332. else
  333. {
  334. sb.Append(NextDigit(2));
  335. sb.Append(NextDigit(7));
  336. }
  337. }
  338. SByte result;
  339. bool parsed = SByte.TryParse(sb.ToString(), out result);
  340. if (parsed)
  341. return result;
  342. return source;
  343. }
  344. /// <summary>
  345. /// Gets the randomized Single value with same number of digits that in source value.
  346. /// </summary>
  347. /// <param name="source">The source Single value.</param>
  348. /// <returns>Random Single value based on source.</returns>
  349. public float RandomizeFloat(float source)
  350. {
  351. return (float)RandomizeDecimal((decimal)source);
  352. }
  353. /// <summary>
  354. /// Gets the randomized string with same length and same whitespaces that in source string.
  355. /// </summary>
  356. /// <param name="source">The source string.</param>
  357. /// <returns>Random string based on source string.</returns>
  358. public string RandomizeString(string source)
  359. {
  360. StringBuilder sb = new StringBuilder();
  361. foreach (char c in source)
  362. {
  363. if (char.IsWhiteSpace(c))
  364. sb.Append(c);
  365. else if (char.IsLetter(c))
  366. sb.Append(NextLetter(c));
  367. else if (char.IsDigit(c))
  368. sb.Append(NextDigit());
  369. else
  370. sb.Append(c);
  371. }
  372. return sb.ToString();
  373. }
  374. /// <summary>
  375. /// Gets the randomized UInt16 value with same number of digits that in source value.
  376. /// </summary>
  377. /// <param name="source">The source UInt16 value.</param>
  378. /// <returns>Random UInt16 value based on source.</returns>
  379. public UInt16 RandomizeUInt16(UInt16 source)
  380. {
  381. StringBuilder sb = new StringBuilder();
  382. int length = source.ToString(CultureInfo.InvariantCulture).Length;
  383. int maxLength = UInt16.MaxValue.ToString(CultureInfo.InvariantCulture).Length;
  384. if (length < maxLength)
  385. {
  386. sb.Append(NextDigit(1, 9));
  387. sb.Append(NextDigits(length - 1));
  388. }
  389. else // Guarantee a value less than 65 000.
  390. {
  391. int next = NextDigit(1, 6);
  392. sb.Append(next);
  393. if (next < 6)
  394. sb.Append(NextDigits(maxLength - 1));
  395. else
  396. {
  397. sb.Append(NextDigit(4));
  398. sb.Append(NextDigits(maxLength - 2));
  399. }
  400. }
  401. UInt16 result;
  402. bool parsed = UInt16.TryParse(sb.ToString(), out result);
  403. if (parsed)
  404. return result;
  405. return source;
  406. }
  407. /// <summary>
  408. /// Gets the randomized UInt32 value with same number of digits that in source value.
  409. /// </summary>
  410. /// <param name="source">The source UInt32 value.</param>
  411. /// <returns>Random UInt32 value based on source.</returns>
  412. public UInt32 RandomizeUInt32(UInt32 source)
  413. {
  414. StringBuilder sb = new StringBuilder();
  415. int length = source.ToString(CultureInfo.InvariantCulture).Length;
  416. int maxLength = UInt32.MaxValue.ToString(CultureInfo.InvariantCulture).Length;
  417. if (length < maxLength)
  418. {
  419. sb.Append(NextDigit(1, 9));
  420. sb.Append(NextDigits(length - 1));
  421. }
  422. else // Guarantee a value less than 4 200 000 000.
  423. {
  424. int next = NextDigit(1, 4);
  425. sb.Append(next);
  426. if (next < 4)
  427. sb.Append(NextDigits(maxLength - 1));
  428. else
  429. {
  430. sb.Append(NextDigit(1));
  431. sb.Append(NextDigits(maxLength - 2));
  432. }
  433. }
  434. UInt32 result;
  435. bool parsed = UInt32.TryParse(sb.ToString(), out result);
  436. if (parsed)
  437. return result;
  438. return source;
  439. }
  440. /// <summary>
  441. /// Gets the randomized UInt64 value with same number of digits that in source value.
  442. /// </summary>
  443. /// <param name="source">The source UInt64 value.</param>
  444. /// <returns>Random UInt64 value based on source.</returns>
  445. public UInt64 RandomizeUInt64(UInt64 source)
  446. {
  447. StringBuilder sb = new StringBuilder();
  448. int length = source.ToString(CultureInfo.InvariantCulture).Length;
  449. int maxLength = UInt64.MaxValue.ToString(CultureInfo.InvariantCulture).Length;
  450. if (length < maxLength)
  451. {
  452. sb.Append(NextDigit(1, 9));
  453. sb.Append(NextDigits(length - 1));
  454. }
  455. else // Guarantee a value less than 18 400 000 000 000 000 000.
  456. {
  457. sb.Append(1);
  458. int next = NextDigit(8);
  459. sb.Append(next);
  460. if (next < 8)
  461. sb.Append(NextDigits(maxLength - 2));
  462. else
  463. {
  464. sb.Append(NextDigit(3));
  465. sb.Append(NextDigits(maxLength - 3));
  466. }
  467. }
  468. UInt64 result;
  469. bool parsed = UInt64.TryParse(sb.ToString(), out result);
  470. if (parsed)
  471. return result;
  472. return source;
  473. }
  474. /// <summary>
  475. /// Gets randomized object based on the source object.
  476. /// </summary>
  477. /// <param name="source">The source object.</param>
  478. /// <param name="type">The type of object.</param>
  479. /// <returns>Random object based on source.</returns>
  480. public object GetRandomObject(object source, Type type)
  481. {
  482. try
  483. {
  484. if (type == typeof(string))
  485. return RandomizeString((string)source);
  486. else if (type == typeof(Int32))
  487. return RandomizeInt32((Int32)source);
  488. else if (type == typeof(double))
  489. return RandomizeDouble((double)source);
  490. else if (type == typeof(DateTime))
  491. return NextDay(new DateTime(1990, 1, 1));
  492. else if (type == typeof(Int64))
  493. return RandomizeInt64((Int64)source);
  494. else if (type == typeof(decimal))
  495. return RandomizeDecimal((decimal)source);
  496. else if (type == typeof(Int16))
  497. return RandomizeInt16((Int16)source);
  498. else if (type == typeof(float))
  499. return RandomizeFloat((float)source);
  500. else if (type == typeof(char))
  501. return NextChar();
  502. else if (type == typeof(byte))
  503. return NextByte();
  504. else if (type == typeof(UInt32))
  505. return RandomizeUInt32((UInt32)source);
  506. else if (type == typeof(UInt64))
  507. return RandomizeUInt64((UInt64)source);
  508. else if (type == typeof(UInt16))
  509. return RandomizeUInt16((UInt16)source);
  510. else if (type == typeof(byte[]))
  511. return NextBytes(((byte[])source).Length);
  512. else if (type == typeof(SByte))
  513. return RandomizeSByte((sbyte)source);
  514. else if (type == typeof(TimeSpan))
  515. return NextTimeSpanBetweenHours(0, 24);
  516. }
  517. catch
  518. {
  519. return source;
  520. }
  521. return source;
  522. }
  523. /// <summary>
  524. /// Randomizes datasources.
  525. /// </summary>
  526. /// <param name="datasources">Collection of datasources.</param>
  527. public void RandomizeDataSources(DataSourceCollection datasources)
  528. {
  529. Dictionary<string, FRColumnInfo> uniquesAndRelations = new Dictionary<string, FRColumnInfo>();
  530. // Get list of related columns and columns with unique values with their type and length.
  531. foreach (DataSourceBase datasource in datasources)
  532. {
  533. if (datasource is TableDataSource)
  534. {
  535. DataTable table = (datasource as TableDataSource).Table;
  536. DataSet ds = table.DataSet;
  537. int length = table.Rows.Count;
  538. for (int c = 0; c < table.Columns.Count; c++)
  539. foreach (DataColumn column in table.Columns)
  540. {
  541. if (column.Unique)
  542. {
  543. if (!uniquesAndRelations.ContainsKey(column.ColumnName))
  544. uniquesAndRelations.Add(column.ColumnName, new FRColumnInfo(column.DataType, length));
  545. }
  546. }
  547. foreach (DataRelation dr in ds.Relations)
  548. {
  549. foreach (DataColumn dc in dr.ParentColumns)
  550. {
  551. if (!uniquesAndRelations.ContainsKey(dc.ColumnName))
  552. uniquesAndRelations.Add(dc.ColumnName, new FRColumnInfo(dc.DataType, length));
  553. }
  554. foreach (DataColumn dc in dr.ChildColumns)
  555. {
  556. if (!uniquesAndRelations.ContainsKey(dc.ColumnName))
  557. uniquesAndRelations.Add(dc.ColumnName, new FRColumnInfo(dc.DataType, length));
  558. }
  559. }
  560. }
  561. }
  562. Dictionary<string, FRRandomFieldValueCollection> dict = new Dictionary<string, FRRandomFieldValueCollection>();
  563. foreach (KeyValuePair<string, FRColumnInfo> pair in uniquesAndRelations)
  564. {
  565. dict.Add(pair.Key, new FRRandomFieldValueCollection());
  566. }
  567. // Get values for related columns and columns with unique values.
  568. foreach (DataSourceBase datasource in datasources)
  569. {
  570. if (datasource is TableDataSource)
  571. {
  572. DataTable table = (datasource as TableDataSource).Table;
  573. for (int c = 0; c < table.Columns.Count; c++)
  574. {
  575. DataColumn column = table.Columns[c];
  576. if (!uniquesAndRelations.ContainsKey(column.ColumnName))
  577. continue;
  578. Type type = uniquesAndRelations[column.ColumnName].Type;
  579. for (int r = 0; r < table.Rows.Count; r++)
  580. {
  581. object val = table.Rows[r][c];
  582. if (val != null && !(val is System.DBNull) && !dict[column.ColumnName].ContainsOrigin(val))
  583. {
  584. object randomVal;
  585. do
  586. {
  587. randomVal = GetRandomObject(val, type);
  588. }
  589. while (dict[column.ColumnName].ContainsRandom(new FRRandomFieldValue(val, randomVal)));
  590. dict[column.ColumnName].Add(new FRRandomFieldValue(val, randomVal));
  591. }
  592. }
  593. }
  594. }
  595. }
  596. // Randomize all table datasources.
  597. foreach (DataSourceBase datasource in datasources)
  598. {
  599. if (datasource is TableDataSource)
  600. {
  601. (datasource as TableDataSource).StoreData = true;
  602. DataTable table = (datasource as TableDataSource).Table;
  603. for (int c = 0; c < table.Columns.Count; c++)
  604. {
  605. if (table.Columns[c].ReadOnly)
  606. continue;
  607. Type type = table.Columns[c].DataType;
  608. for (int r = 0; r < table.Rows.Count; r++)
  609. {
  610. object val = table.Rows[r][c];
  611. if (val != null && !(val is System.DBNull))
  612. {
  613. if (uniquesAndRelations.ContainsKey(table.Columns[c].ColumnName))
  614. table.Rows[r][c] = dict[table.Columns[c].ColumnName].GetRandom(val);
  615. else
  616. table.Rows[r][c] = GetRandomObject(val, type);
  617. }
  618. }
  619. }
  620. }
  621. }
  622. }
  623. #endregion Public Methods
  624. #region Constructors
  625. /// <summary>
  626. /// Initializes a new instance of the <see cref="FRRandom"/> class.
  627. /// </summary>
  628. public FRRandom()
  629. {
  630. random = new Random();
  631. }
  632. #endregion Constructors
  633. }
  634. /// <summary>
  635. /// Represents information about column.
  636. /// </summary>
  637. public class FRColumnInfo
  638. {
  639. #region Fields
  640. private Type type;
  641. private int length;
  642. #endregion Fields
  643. #region Properties
  644. /// <summary>
  645. /// Gets or sets the type of column.
  646. /// </summary>
  647. public Type Type
  648. {
  649. get { return type; }
  650. set { type = value; }
  651. }
  652. /// <summary>
  653. /// Gets or sets the length of column.
  654. /// </summary>
  655. public int Length
  656. {
  657. get { return length; }
  658. set { length = value; }
  659. }
  660. #endregion Properties
  661. #region Constructors
  662. /// <summary>
  663. /// Initializes a new instance of the <see cref="FRColumnInfo"/> class.
  664. /// </summary>
  665. /// <param name="type">The type of column.</param>
  666. /// <param name="length">The lenght of column.</param>
  667. public FRColumnInfo(Type type, int length)
  668. {
  669. this.type = type;
  670. this.length = length;
  671. }
  672. #endregion Constructors
  673. }
  674. /// <summary>
  675. /// Represents random value of field.
  676. /// </summary>
  677. public class FRRandomFieldValue
  678. {
  679. #region Fields
  680. private object origin;
  681. private object random;
  682. #endregion Fields
  683. #region Properties
  684. /// <summary>
  685. /// Gets or sets the original value of field.
  686. /// </summary>
  687. public object Origin
  688. {
  689. get { return origin; }
  690. set { origin = value; }
  691. }
  692. /// <summary>
  693. /// Gets or sets the random value of field.
  694. /// </summary>
  695. public object Random
  696. {
  697. get { return random; }
  698. set { random = value; }
  699. }
  700. #endregion Properties
  701. #region Constructors
  702. /// <summary>
  703. /// Initializes a new instance of the <see cref="FRRandomFieldValue"/> class.
  704. /// </summary>
  705. /// <param name="origin">The original value of field.</param>
  706. /// <param name="random">The random value of field.</param>
  707. public FRRandomFieldValue(object origin, object random)
  708. {
  709. this.origin = origin;
  710. this.random = random;
  711. }
  712. #endregion Constructors
  713. }
  714. /// <summary>
  715. /// Represents collection of random values of field.
  716. /// </summary>
  717. public class FRRandomFieldValueCollection
  718. {
  719. #region Fields
  720. private readonly List<FRRandomFieldValue> list;
  721. #endregion Fields
  722. #region Properties
  723. #endregion Properties
  724. #region Constructors
  725. /// <summary>
  726. /// Initializes a new instance of the <see cref="FRRandomFieldValueCollection"/> class.
  727. /// </summary>
  728. public FRRandomFieldValueCollection()
  729. {
  730. list = new List<FRRandomFieldValue>();
  731. }
  732. #endregion Constructors
  733. #region Public Methods
  734. /// <summary>
  735. /// Adds an object to the end of this collection.
  736. /// </summary>
  737. /// <param name="value">Object to add.</param>
  738. public void Add(FRRandomFieldValue value)
  739. {
  740. list.Add(value);
  741. }
  742. /// <summary>
  743. /// Determines whether an element with the same origin value is in the collection.
  744. /// </summary>
  745. /// <param name="origin">The object to locate in the collection.</param>
  746. /// <returns><b>true</b> if object is found in the collection; otherwise, <b>false</b>.</returns>
  747. public bool ContainsOrigin(object origin)
  748. {
  749. foreach (FRRandomFieldValue value in list)
  750. {
  751. if (value.Origin == origin)
  752. return true;
  753. }
  754. return false;
  755. }
  756. /// <summary>
  757. /// Determines whether an element with the same random value is in the collection.
  758. /// </summary>
  759. /// <param name="random">The object to locate in the collection.</param>
  760. /// <returns><b>true</b> if object is found in the collection; otherwise, <b>false</b>.</returns>
  761. public bool ContainsRandom(object random)
  762. {
  763. foreach (FRRandomFieldValue value in list)
  764. {
  765. if (value.Random == random)
  766. return true;
  767. }
  768. return false;
  769. }
  770. /// <summary>
  771. /// Gets the random value for specified origin.
  772. /// </summary>
  773. /// <param name="origin">The origin value.</param>
  774. /// <returns>The random value.</returns>
  775. public object GetRandom(object origin)
  776. {
  777. foreach (FRRandomFieldValue value in list)
  778. {
  779. if (value.Origin == origin)
  780. return value.Random;
  781. }
  782. return origin;
  783. }
  784. #endregion Public Methods
  785. }
  786. }