86 lines
2.8 KiB
C#
86 lines
2.8 KiB
C#
![]() |
// -----------------------------------------------------------------------------
|
|||
|
// 让 .NET 开发更简单,更通用,更流行。
|
|||
|
// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd.
|
|||
|
//
|
|||
|
// 框架名称:Furion
|
|||
|
// 框架作者:百小僧
|
|||
|
// 框架版本:2.7.9
|
|||
|
// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion
|
|||
|
// Github:https://github.com/monksoul/Furion
|
|||
|
// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE)
|
|||
|
// -----------------------------------------------------------------------------
|
|||
|
|
|||
|
using System;
|
|||
|
using System.Security.Cryptography;
|
|||
|
|
|||
|
namespace HT.Cloud.Code
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 连续 GUID ID 生成器
|
|||
|
/// <para>代码参考自:https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/blob/ebe011a6f1b2a2a9709fe558cfc7ed3215b55c37/src/EFCore.MySql/ValueGeneration/Internal/MySqlSequentialGuidValueGenerator.cs </para>
|
|||
|
/// </summary>
|
|||
|
public class SequentialGuidIDGenerator : IDistributedIDGenerator
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 随机数生成器
|
|||
|
/// </summary>
|
|||
|
private static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create();
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 生成逻辑
|
|||
|
/// </summary>
|
|||
|
/// <param name="idGeneratorOptions"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public object Create(object idGeneratorOptions = null)
|
|||
|
{
|
|||
|
// According to RFC 4122:
|
|||
|
// dddddddd-dddd-Mddd-Ndrr-rrrrrrrrrrrr
|
|||
|
// - M = RFC version, in this case '4' for random UUID
|
|||
|
// - N = RFC variant (plus other bits), in this case 0b1000 for variant 1
|
|||
|
// - d = nibbles based on UTC date/time in ticks
|
|||
|
// - r = nibbles based on random bytes
|
|||
|
|
|||
|
var options = (idGeneratorOptions ?? new SequentialGuidSettings()) as SequentialGuidSettings;
|
|||
|
|
|||
|
var randomBytes = new byte[7];
|
|||
|
_rng.GetBytes(randomBytes);
|
|||
|
var ticks = (ulong)options.TimeNow.Ticks;
|
|||
|
|
|||
|
var uuidVersion = (ushort)4;
|
|||
|
var uuidVariant = (ushort)0b1000;
|
|||
|
|
|||
|
var ticksAndVersion = (ushort)((ticks << 48 >> 52) | (ushort)(uuidVersion << 12));
|
|||
|
var ticksAndVariant = (byte)((ticks << 60 >> 60) | (byte)(uuidVariant << 4));
|
|||
|
|
|||
|
if (options.LittleEndianBinary16Format)
|
|||
|
{
|
|||
|
var guidBytes = new byte[16];
|
|||
|
var tickBytes = BitConverter.GetBytes(ticks);
|
|||
|
if (BitConverter.IsLittleEndian)
|
|||
|
{
|
|||
|
Array.Reverse(tickBytes);
|
|||
|
}
|
|||
|
|
|||
|
Buffer.BlockCopy(tickBytes, 0, guidBytes, 0, 6);
|
|||
|
guidBytes[6] = (byte)(ticksAndVersion << 8 >> 8);
|
|||
|
guidBytes[7] = (byte)(ticksAndVersion >> 8);
|
|||
|
guidBytes[8] = ticksAndVariant;
|
|||
|
Buffer.BlockCopy(randomBytes, 0, guidBytes, 9, 7);
|
|||
|
|
|||
|
return new Guid(guidBytes);
|
|||
|
}
|
|||
|
|
|||
|
var guid = new Guid((uint)(ticks >> 32), (ushort)(ticks << 32 >> 48), ticksAndVersion,
|
|||
|
ticksAndVariant,
|
|||
|
randomBytes[0],
|
|||
|
randomBytes[1],
|
|||
|
randomBytes[2],
|
|||
|
randomBytes[3],
|
|||
|
randomBytes[4],
|
|||
|
randomBytes[5],
|
|||
|
randomBytes[6]);
|
|||
|
|
|||
|
return guid;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|