zoukankan      html  css  js  c++  java
  • C#生成string类型的唯一ID

    using System;
    using System.Diagnostics;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading;
    
    namespace 命名空间
    {
        /// <summary>
        /// Represents an ObjectId (see also BsonObjectId).
        /// </summary>
        [Serializable]
        public struct ObjectId : IComparable<ObjectId>, IEquatable<ObjectId>
        {
            #region private static fields
            private static ObjectId emptyInstance = default(ObjectId);
            private static int staticMachine;
            private static short staticPid;
            private static int staticIncrement; // high byte will be masked out when generating new ObjectId
            #endregion
    
            #region private fields
            // we're using 14 bytes instead of 12 to hold the ObjectId in memory but unlike a byte[] there is no additional object on the heap
            // the extra two bytes are not visible to anyone outside of this class and they buy us considerable simplification
            // an additional advantage of this representation is that it will serialize to JSON without any 64 bit overflow problems
            private int timestamp;
            private int machine;
            private short pid;
            private int increment;
            #endregion
    
            #region static constructor
            static ObjectId()
            {
                staticMachine = GetMachineHash();//获取机器名称
                staticPid = (short)Process.GetCurrentProcess().Id; // use low order two bytes only 
                //取得新的 Process 元件,並將它與目前作用中的處理序相關聯。
                staticIncrement = (new Random()).Next();//返回非负随机数
            }
            #endregion
    
            #region constructors
            /// <summary>
            /// Initializes a new instance of the ObjectId class.
            /// </summary>
            /// <param name="bytes">The value.</param>
            public ObjectId(
                byte[] bytes
            )
            {
                Unpack(bytes, out timestamp, out machine, out pid, out increment);
            }
    
            /// <summary>
            /// Initializes a new instance of the ObjectId class.
            /// </summary>
            /// <param name="timestamp">The timestamp.</param>
            /// <param name="machine">The machine hash.</param>
            /// <param name="pid">The PID.</param>
            /// <param name="increment">The increment.</param>
            public ObjectId(
                int timestamp,
                int machine,
                short pid,
                int increment
            )
            {
                this.timestamp = timestamp;
                this.machine = machine;
                this.pid = pid;
                this.increment = increment;
            }
    
            /// <summary>
            /// Initializes a new instance of the ObjectId class.
            /// </summary>
            /// <param name="value">The value.</param>
            public ObjectId(
                string value
            )
            {
                Unpack(Utils.ParseHexString(value), out timestamp, out machine, out pid, out increment);
            }
            #endregion
    
            #region public static properties
            /// <summary>
            /// Gets an instance of ObjectId where the value is empty.
            /// </summary>
            public static ObjectId Empty
            {
                get { return emptyInstance; }
            }
            #endregion
    
            #region public properties
            /// <summary>
            /// Gets the timestamp.
            /// </summary>
            public int Timestamp
            {
                get { return timestamp; }
            }
    
            /// <summary>
            /// Gets the machine.
            /// </summary>
            public int Machine
            {
                get { return machine; }
            }
    
            /// <summary>
            /// Gets the PID.
            /// </summary>
            public short Pid
            {
                get { return pid; }
            }
    
            /// <summary>
            /// Gets the increment.
            /// </summary>
            public int Increment
            {
                get { return increment; }
            }
    
            /// <summary>
            /// Gets the creation time (derived from the timestamp).
            /// </summary>
            public DateTime CreationTime
            {
                get { return Constants.UnixEpoch.AddSeconds(timestamp); }
            }
            #endregion
    
            #region public operators
            /// <summary>
            /// Compares two ObjectIds.
            /// </summary>
            /// <param name="lhs">The first ObjectId.</param>
            /// <param name="rhs">The other ObjectId</param>
            /// <returns>True if the first ObjectId is less than the second ObjectId.</returns>
            public static bool operator <(
                ObjectId lhs,
                ObjectId rhs
            )
            {
                return lhs.CompareTo(rhs) < 0;
            }
    
            /// <summary>
            /// Compares two ObjectIds.
            /// </summary>
            /// <param name="lhs">The first ObjectId.</param>
            /// <param name="rhs">The other ObjectId</param>
            /// <returns>True if the first ObjectId is less than or equal to the second ObjectId.</returns>
            public static bool operator <=(
                ObjectId lhs,
                ObjectId rhs
            )
            {
                return lhs.CompareTo(rhs) <= 0;
            }
    
            /// <summary>
            /// Compares two ObjectIds.
            /// </summary>
            /// <param name="lhs">The first ObjectId.</param>
            /// <param name="rhs">The other ObjectId.</param>
            /// <returns>True if the two ObjectIds are equal.</returns>
            public static bool operator ==(
                ObjectId lhs,
                ObjectId rhs
            )
            {
                return lhs.Equals(rhs);
            }
    
            /// <summary>
            /// Compares two ObjectIds.
            /// </summary>
            /// <param name="lhs">The first ObjectId.</param>
            /// <param name="rhs">The other ObjectId.</param>
            /// <returns>True if the two ObjectIds are not equal.</returns>
            public static bool operator !=(
                ObjectId lhs,
                ObjectId rhs
            )
            {
                return !lhs.Equals(rhs);
            }
    
            /// <summary>
            /// Compares two ObjectIds.
            /// </summary>
            /// <param name="lhs">The first ObjectId.</param>
            /// <param name="rhs">The other ObjectId</param>
            /// <returns>True if the first ObjectId is greather than or equal to the second ObjectId.</returns>
            public static bool operator >=(
                ObjectId lhs,
                ObjectId rhs
            )
            {
                return lhs.CompareTo(rhs) >= 0;
            }
    
            /// <summary>
            /// Compares two ObjectIds.
            /// </summary>
            /// <param name="lhs">The first ObjectId.</param>
            /// <param name="rhs">The other ObjectId</param>
            /// <returns>True if the first ObjectId is greather than the second ObjectId.</returns>
            public static bool operator >(
                ObjectId lhs,
                ObjectId rhs
            )
            {
                return lhs.CompareTo(rhs) > 0;
            }
            #endregion
    
            #region public static methods
            /// <summary>
            /// Generates a new ObjectId with a unique value.
            /// </summary>
            /// <returns>A ObjectId.</returns>
            public static ObjectId GenerateNewId()
            {
                int timestamp = GetCurrentTimestamp();//根据时间获取
                int increment = Interlocked.Increment(ref ObjectId.staticIncrement) & 0x00ffffff; // only use low order 3 bytes
                return new ObjectId(timestamp, staticMachine, staticPid, increment);
            }
    
            public static string NewId()
            {
                return GenerateNewId().ToString();
            }
    
            /// <summary>
            /// Packs the components of an ObjectId into a byte array.
            /// </summary>
            /// <param name="timestamp">The timestamp.</param>
            /// <param name="machine">The machine hash.</param>
            /// <param name="pid">The PID.</param>
            /// <param name="increment">The increment.</param>
            /// <returns>A byte array.</returns>
            public static byte[] Pack(
                int timestamp,
                int machine,
                short pid,
                int increment
            )
            {
                byte[] bytes = new byte[12];
                bytes[0] = (byte)(timestamp >> 24);
                bytes[1] = (byte)(timestamp >> 16);
                bytes[2] = (byte)(timestamp >> 8);
                bytes[3] = (byte)(timestamp);
                bytes[4] = (byte)(machine >> 16);
                bytes[5] = (byte)(machine >> 8);
                bytes[6] = (byte)(machine);
                bytes[7] = (byte)(pid >> 8);
                bytes[8] = (byte)(pid);
                bytes[9] = (byte)(increment >> 16);
                bytes[10] = (byte)(increment >> 8);
                bytes[11] = (byte)(increment);
                return bytes;
            }
    
            /// <summary>
            /// Parses a string and creates a new ObjectId.
            /// </summary>
            /// <param name="s">The string value.</param>
            /// <returns>A ObjectId.</returns>
            public static ObjectId Parse(
                string s
            )
            {
                ObjectId objectId;
                if (TryParse(s, out objectId))
                {
                    return objectId;
                }
                else
                {
                    var message = string.Format("'{0}' is not a valid 24 digit hex string.", s);
                    throw new FormatException(message);
                }
            }
    
            /// <summary>
            /// Tries to parse a string and create a new ObjectId.
            /// </summary>
            /// <param name="s">The string value.</param>
            /// <param name="objectId">The new ObjectId.</param>
            /// <returns>True if the string was parsed successfully.</returns>
            public static bool TryParse(
                string s,
                out ObjectId objectId
            )
            {
                if (s != null && s.Length == 24)
                {
                    byte[] bytes;
                    if (Utils.TryParseHexString(s, out bytes))
                    {
                        objectId = new ObjectId(bytes);
                        return true;
                    }
                }
    
                objectId = default(ObjectId);
                return false;
            }
    
            /// <summary>
            /// Unpacks a byte array into the components of an ObjectId.
            /// </summary>
            /// <param name="bytes">A byte array.</param>
            /// <param name="timestamp">The timestamp.</param>
            /// <param name="machine">The machine hash.</param>
            /// <param name="pid">The PID.</param>
            /// <param name="increment">The increment.</param>
            public static void Unpack(
                byte[] bytes,
                out int timestamp,
                out int machine,
                out short pid,
                out int increment
            )
            {
                if (bytes.Length != 12)
                {
                    throw new ArgumentOutOfRangeException("Byte array must be 12 bytes long.");
                }
                timestamp = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];
                machine = (bytes[4] << 16) + (bytes[5] << 8) + bytes[6];
                pid = (short)((bytes[7] << 8) + bytes[8]);
                increment = (bytes[9] << 16) + (bytes[10] << 8) + bytes[11];
            }
            #endregion
    
            #region private static methods
            private static int GetMachineHash()
            {
                var hostName = Environment.MachineName; // use instead of Dns.HostName so it will work offline
                var md5 = MD5.Create();//哈希算法的默认实现的实例
                var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(hostName));//在派生类中重写时,将指定的System.String中的所有字符编码
                return (hash[0] << 16) + (hash[1] << 8) + hash[2]; // use first 3 bytes of hash
            }
    
            private static int GetCurrentTimestamp()
            {
                DateTime now = DateTime.UtcNow;
                return (int)Math.Floor((now - Constants.UnixEpoch).TotalSeconds);
            }
            #endregion
    
            #region public methods
            /// <summary>
            /// Compares this ObjectId to another ObjectId.
            /// </summary>
            /// <param name="other">The other ObjectId.</param>
            /// <returns>A 32-bit signed integer that indicates whether this ObjectId is less than, equal to, or greather than the other.</returns>
            public int CompareTo(
                ObjectId other
            )
            {
                int r = timestamp.CompareTo(other.timestamp);
                if (r != 0) { return r; }
                r = machine.CompareTo(other.machine);
                if (r != 0) { return r; }
                r = pid.CompareTo(other.pid);
                if (r != 0) { return r; }
                return increment.CompareTo(other.increment);
            }
    
            /// <summary>
            /// Compares this ObjectId to another ObjectId.
            /// </summary>
            /// <param name="rhs">The other ObjectId.</param>
            /// <returns>True if the two ObjectIds are equal.</returns>
            public bool Equals(
                ObjectId rhs
            )
            {
                return
                    this.timestamp == rhs.timestamp &&
                    this.machine == rhs.machine &&
                    this.pid == rhs.pid &&
                    this.increment == rhs.increment;
            }
    
            /// <summary>
            /// Compares this ObjectId to another object.
            /// </summary>
            /// <param name="obj">The other object.</param>
            /// <returns>True if the other object is an ObjectId and equal to this one.</returns>
            public override bool Equals(
                object obj
            )
            {
                if (obj is ObjectId)
                {
                    return Equals((ObjectId)obj);
                }
                else
                {
                    return false;
                }
            }
    
            /// <summary>
            /// Gets the hash code.
            /// </summary>
            /// <returns>The hash code.</returns>
            public override int GetHashCode()
            {
                int hash = 17;
                hash = 37 * hash + timestamp.GetHashCode();
                hash = 37 * hash + machine.GetHashCode();
                hash = 37 * hash + pid.GetHashCode();
                hash = 37 * hash + increment.GetHashCode();
                return hash;
            }
    
            /// <summary>
            /// Converts the ObjectId to a byte array.
            /// </summary>
            /// <returns>A byte array.</returns>
            public byte[] ToByteArray()
            {
                return Pack(timestamp, machine, pid, increment);
            }
    
            /// <summary>
            /// Returns a string representation of the value.
            /// </summary>
            /// <returns>A string representation of the value.</returns>
            public override string ToString()
            {
                return Utils.ToHexString(Pack(timestamp, machine, pid, increment));
            }
            #endregion
    
    
            internal static class Utils
            {
                /// <summary>
                /// Tries to parse a hex string to a byte array.
                /// </summary>
                /// <param name="s">The hex string.</param>
                /// <param name="bytes">A byte array.</param>
                /// <returns>True if the hex string was successfully parsed.</returns>
                public static bool TryParseHexString(
                    string s,
                    out byte[] bytes
                )
                {
                    if (s != null)
                    {
                        if ((s.Length & 1) != 0) { s = "0" + s; } // make length of s even
                        bytes = new byte[s.Length / 2];
                        for (int i = 0; i < bytes.Length; i++)
                        {
                            string hex = s.Substring(2 * i, 2);
                            try
                            {
                                byte b = Convert.ToByte(hex, 16);
                                bytes[i] = b;
                            }
                            catch (FormatException)
                            {
                                bytes = null;
                                return false;
                            }
                        }
                        return true;
                    }
    
                    bytes = null;
                    return false;
                }
    
                /// <summary>
                /// Tries to parse a hex string to a byte array.
                /// </summary>
                /// <param name="s">The hex string.</param>
                /// <param name="bytes">A byte array.</param>
                /// <returns>True if the hex string was successfully parsed.</returns>
                public static byte[] ParseHexString(string s)
                {
                    byte[] bytes;
                    if (!TryParseHexString(s, out bytes))
                    {
                        var message = string.Format("'{0}' is not a valid hex string.", s);
                        throw new FormatException(message);
                    }
                    return bytes;
                }
    
                /// <summary>
                /// Converts a byte array to a hex string.
                /// </summary>
                /// <param name="bytes">The byte array.</param>
                /// <returns>A hex string.</returns>
                public static string ToHexString(
                    byte[] bytes
                )
                {
                    var sb = new StringBuilder(bytes.Length * 2);
                    foreach (var b in bytes)
                    {
                        sb.AppendFormat("{0:x2}", b);
                    }
                    return sb.ToString();
                }
            }
    
            internal static class Constants
            {
                #region private static fields
                private static readonly long dateTimeMaxValueMillisecondsSinceEpoch;
                private static readonly long dateTimeMinValueMillisecondsSinceEpoch;
                private static readonly DateTime unixEpoch;
                #endregion
    
                #region static constructor
                static Constants()
                {
                    // unixEpoch has to be initialized first
                    unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                    dateTimeMaxValueMillisecondsSinceEpoch = (DateTime.MaxValue - unixEpoch).Ticks / 10000;
                    dateTimeMinValueMillisecondsSinceEpoch = (DateTime.MinValue - unixEpoch).Ticks / 10000;
                }
                #endregion
    
                #region public static properties
                /// <summary>
                /// Gets the number of milliseconds since the Unix epoch for DateTime.MaxValue.
                /// </summary>
                public static long DateTimeMaxValueMillisecondsSinceEpoch
                {
                    get { return dateTimeMaxValueMillisecondsSinceEpoch; }
                }
    
                /// <summary>
                /// Gets the number of milliseconds since the Unix epoch for DateTime.MinValue.
                /// </summary>
                public static long DateTimeMinValueMillisecondsSinceEpoch
                {
                    get { return dateTimeMinValueMillisecondsSinceEpoch; }
                }
    
                /// <summary>
                /// Gets the Unix Epoch for BSON DateTimes (1970-01-01).
                /// </summary>
                public static DateTime UnixEpoch { get { return unixEpoch; } }
                #endregion
            }
    
        }
    }
  • 相关阅读:
    终于和Java碰面了
    Servlet学习-MVC开发模式
    Servlet学习-数据库的操作
    Servlet学习-sendRedirect()和forward()
    Servlet学习-request
    Servlet学习-乱码解决方案
    Servlet学习-response
    Servlet学习-页面设置不缓存
    软件构造 第一章第二节 软件开发的质量属性
    软件构造 第二章 第一节 软件生命周期和版本控制
  • 原文地址:https://www.cnblogs.com/wuhuisheng/p/2471077.html
Copyright © 2011-2022 走看看