| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 | using System;using System.Security.Cryptography;namespace Ips.Library.Basic{    public class GuidSeq    {        public static GuidSeq Instance { get; } = new GuidSeq();        private static readonly RandomNumberGenerator Rng = RandomNumberGenerator.Create();        public SequentialGuidDatabaseType DatabaseType { get; set; }        private GuidSeq()        {            DatabaseType = SequentialGuidDatabaseType.PostgreSql;        }        public Guid Create()        {            return Create(DatabaseType);        }        public Guid Create(SequentialGuidDatabaseType databaseType)        {            switch (databaseType)            {                case SequentialGuidDatabaseType.SqlServer:                    return Create(SequentialGuidType.SequentialAtEnd);                case SequentialGuidDatabaseType.Oracle:                    return Create(SequentialGuidType.SequentialAsBinary);                case SequentialGuidDatabaseType.MySql:                    return Create(SequentialGuidType.SequentialAsString);                case SequentialGuidDatabaseType.PostgreSql:                    return Create(SequentialGuidType.SequentialAsString);                default:                    throw new InvalidOperationException();            }        }        public Guid Create(SequentialGuidType guidType)        {            var randomBytes = new byte[10];            lock (Rng)            {                Rng.GetBytes(randomBytes);            }            long timestamp = DateTime.UtcNow.Ticks / 10000L;            byte[] timestampBytes = BitConverter.GetBytes(timestamp);            if (BitConverter.IsLittleEndian)            {                Array.Reverse(timestampBytes);            }            byte[] guidBytes = new byte[16];            switch (guidType)            {                case SequentialGuidType.SequentialAsString:                case SequentialGuidType.SequentialAsBinary:                    Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6);                    Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10);                    if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian)                    {                        Array.Reverse(guidBytes, 0, 4);                        Array.Reverse(guidBytes, 4, 2);                    }                    break;                case SequentialGuidType.SequentialAtEnd:                    Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10);                    Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6);                    break;            }            return new Guid(guidBytes);        }        public enum SequentialGuidDatabaseType        {            SqlServer,            Oracle,            MySql,            PostgreSql,        }        public enum SequentialGuidType        {            SequentialAsString,            SequentialAsBinary,            SequentialAtEnd        }    }}
 |