using System; using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Threading; /// <summary> /// ID 生成器 /// </summary> public class IDFactory { #region Static Fields /// <summary> /// The factory. /// </summary> private static IDFactory factory; #endregion #region Fields /// <summary> /// The init millisecond. /// </summary> private readonly ulong InitMillisecond; /// <summary> /// The m watch. /// </summary> private readonly Stopwatch mWatch = new Stopwatch(); /// <summary> /// The m current millisecond. /// </summary> private ulong mCurrentMillisecond; /// <summary> /// The m seed. /// </summary> private byte mSeed; #endregion #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="IDFactory" /> class. /// </summary> public IDFactory() { this.InitMillisecond = (ulong)(DateTime.Now - DateTime.Parse("2015-1-1")).TotalMilliseconds; this.mWatch.Restart(); } static IDFactory() { LoadIPGroup(); } #endregion #region Public Properties /// <summary> /// Gets or sets the group. /// </summary> public static byte Group { get; set; } #endregion #region Public Methods and Operators /// <summary> /// 生成 ID 種子 /// </summary> /// <returns>返回ID種子。參見<see cref="long" /></returns> public static long Create() { if (factory == null) { factory = new IDFactory(); } return (long)factory.Next(); } /// <summary> /// 獲取IP /// </summary> public static void LoadIPGroup() { string hostName = Dns.GetHostName(); IPAddress[] addressList = Dns.GetHostAddresses(hostName); foreach (IPAddress ip in addressList) { if (ip.AddressFamily == AddressFamily.InterNetwork) { byte[] data = ip.GetAddressBytes(); uint value = BitConverter.ToUInt32(data, 0); value = value << 16; value = value >> 16; Group = (byte)value; break; } } } /// <summary> /// 生成ID種子 /// </summary> /// <returns> /// The <see cref="ulong" />. /// </returns> public ulong Next() { ulong result = 0; var slock = new SpinLock(); bool gotLock = false; try { while (!gotLock) { slock.Enter(ref gotLock); if (gotLock) { ulong cms = (ulong)this.mWatch.Elapsed.TotalMilliseconds + this.InitMillisecond; if (cms != this.mCurrentMillisecond) { this.mSeed = 0; this.mCurrentMillisecond = cms; } //result = ((ulong)this.Group << 58) | (this.mCurrentMillisecond << 8) | this.mSeed; //result = ((ulong)Group << 9) | (this.mCurrentMillisecond << 17) | this.mSeed; //result = this.mCurrentMillisecond * 1000000 + (ulong)Group * 1000 + this.mSeed; result = this.mCurrentMillisecond * 10000 + (ulong)Group * 10 + this.mSeed; this.mSeed++; } } } finally { if (gotLock) { slock.Exit(); } } return result; } #endregion }