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, );
value = value << ;
value = value >> ;
Group = (byte)value;
break;
}
}
}
/// <summary>
/// 生成ID种子
/// </summary>
/// <returns>
/// The <see cref="ulong" />.
/// </returns>
public ulong Next()
{
ulong result = ;
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 = ;
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 * + (ulong)Group * + this.mSeed;
this.mSeed++;
}
}
}
finally
{
if (gotLock)
{
slock.Exit();
}
}
return result;
}
#endregion
}