IdHelper.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. namespace WingServerCommon.Utilities
  2. {
  3. public static class IdHelper
  4. {
  5. /// <summary>
  6. /// Generate a unique Id.
  7. /// </summary>
  8. /// <returns></returns>
  9. public static T Generate<T>()
  10. {
  11. var guid = Guid.NewGuid();
  12. var type = typeof(T);
  13. if (typeof(T) == typeof(string))
  14. {
  15. return (T)(object)guid.ToString("N").ToUpper();
  16. }
  17. if (typeof(T) == typeof(byte[]))
  18. {
  19. var buffer = guid.ToByteArray();
  20. return (T)Convert.ChangeType(buffer, type);
  21. }
  22. if (typeof(T) == typeof(FasterUId))
  23. {
  24. var guidData = Guid.NewGuid().ToByteArray();
  25. return (T)(object)new FasterUId(guidData);
  26. }
  27. throw new InvalidOperationException($"Operation [Generate<{type.Name}>] is not supported.");
  28. }
  29. /// <summary>
  30. /// Generate a <see cref="FasterUId"/>.
  31. /// </summary>
  32. /// <param name="part1">The first part of the <see cref="FasterUId"/></param>
  33. /// <param name="part2">The second part of the <see cref="FasterUId"/></param>
  34. /// <returns>The unique <see cref="FasterUId"/></returns>
  35. public static FasterUId Generate(long part1, long part2)
  36. {
  37. return new FasterUId(part1, part2);
  38. }
  39. }
  40. /// <summary>
  41. /// A faster Uid implementation.
  42. /// </summary>
  43. public struct FasterUId : IEquatable<FasterUId>
  44. {
  45. public static readonly FasterUId Empty = new FasterUId(0, 0);
  46. public long Part1 { get; set; }
  47. public long Part2 { get; set; }
  48. public FasterUId(long part1, long part2)
  49. {
  50. Part1 = part1;
  51. Part2 = part2;
  52. }
  53. public FasterUId(string id)
  54. {
  55. if (Guid.TryParse(id, out var guid))
  56. {
  57. var guidData = guid.ToByteArray();
  58. using (var ms = new MemoryStream(guidData))
  59. {
  60. var part1Data = new byte[8];
  61. var part2Data = new byte[8];
  62. ms.Read(part1Data, 0, part1Data.Length);
  63. ms.Read(part2Data, 0, part2Data.Length);
  64. Part1 = BitConverter.ToInt64(part1Data, 0);
  65. Part2 = BitConverter.ToInt64(part2Data, 0);
  66. }
  67. }
  68. else
  69. {
  70. throw new InvalidDataException("Can not convert to FasterId, the string is not matched.");
  71. }
  72. }
  73. /// <summary>
  74. /// FasterUId
  75. /// </summary>
  76. /// <param name="data"></param>
  77. public FasterUId(byte[] data)
  78. {
  79. if (data.Length != 16)
  80. {
  81. throw new InvalidDataException("Can not convert to FasterId, the data size is not matched.");
  82. }
  83. using (var ms = new MemoryStream(data))
  84. {
  85. var part1Data = new byte[8];
  86. var part2Data = new byte[8];
  87. ms.Read(part1Data, 0, part1Data.Length);
  88. ms.Read(part2Data, 0, part2Data.Length);
  89. Part1 = BitConverter.ToInt64(part1Data, 0);
  90. Part2 = BitConverter.ToInt64(part2Data, 0);
  91. }
  92. }
  93. /// <summary>
  94. /// Equals FasterUId
  95. /// </summary>
  96. /// <param name="other"></param>
  97. /// <returns></returns>
  98. public bool Equals(FasterUId other)
  99. {
  100. return Part1 == other.Part1 && Part2 == other.Part2;
  101. }
  102. public override bool Equals(object obj)
  103. {
  104. return obj is FasterUId other && Equals(other);
  105. }
  106. public override int GetHashCode()
  107. {
  108. var hashCode = Part1.GetHashCode();
  109. hashCode = (hashCode * 397) ^ Part2.GetHashCode();
  110. return hashCode;
  111. }
  112. public static bool operator ==(FasterUId left, FasterUId right)
  113. {
  114. return left.Equals(right);
  115. }
  116. public static bool operator !=(FasterUId left, FasterUId right)
  117. {
  118. return !left.Equals(right);
  119. }
  120. public static implicit operator byte[](FasterUId id)
  121. {
  122. using (var ms = new MemoryStream())
  123. {
  124. var part1Data = BitConverter.GetBytes(id.Part1);
  125. var part2Data = BitConverter.GetBytes(id.Part2);
  126. ms.Write(part1Data, 0, part1Data.Length);
  127. ms.Write(part2Data, 0, part2Data.Length);
  128. return ms.ToArray();
  129. }
  130. }
  131. public static explicit operator FasterUId(byte[] data)
  132. {
  133. if (data.Length != 16)
  134. {
  135. throw new InvalidDataException("Can not convert to FasterId, the data size is not matched.");
  136. }
  137. using (var ms = new MemoryStream(data))
  138. {
  139. var part1Data = new byte[8];
  140. var part2Data = new byte[8];
  141. ms.Read(part1Data, 0, part1Data.Length);
  142. ms.Read(part2Data, 0, part2Data.Length);
  143. return new FasterUId();
  144. }
  145. }
  146. public override string ToString()
  147. {
  148. using (var ms = new MemoryStream())
  149. {
  150. var part1Data = BitConverter.GetBytes(Part1);
  151. var part2Data = BitConverter.GetBytes(Part2);
  152. ms.Write(part1Data, 0, part1Data.Length);
  153. ms.Write(part2Data, 0, part2Data.Length);
  154. return new Guid(ms.ToArray()).ToString("N").ToUpper();
  155. }
  156. }
  157. }
  158. }