Files
2023-03-03 16:07:50 +08:00

161 lines
3.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// -----------------------------------------------------------------------------
// 让 .NET 开发更简单,更通用,更流行。
// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd.
//
// 框架名称Furion
// 框架作者:百小僧
// 框架版本2.7.9
// 源码地址Gitee https://gitee.com/dotnetchina/Furion
// Githubhttps://github.com/monksoul/Furion
// 开源协议Apache-2.0https://gitee.com/dotnetchina/Furion/blob/master/LICENSE
// -----------------------------------------------------------------------------
using System;
using System.Linq;
using System.Text;
namespace HT.Cloud.Code
{
/// <summary>
/// 短 ID 生成核心代码
/// <para>代码参考自https://github.com/bolorundurowb/shortid </para>
/// </summary>
public static class ShortIDGen
{
/// <summary>
/// 短 ID 生成器期初数据
/// </summary>
private static Random _random = new();
private const string Bigs = "ABCDEFGHIJKLMNPQRSTUVWXY";
private const string Smalls = "abcdefghjklmnopqrstuvwxyz";
private const string Numbers = "0123456789";
private const string Specials = "_-";
private static string _pool = $"{Smalls}{Bigs}";
/// <summary>
/// 线程安全锁
/// </summary>
private static readonly object ThreadLock = new();
/// <summary>
/// 生成目前比较主流的短 ID
/// <para>包含字母、数字,不包含特殊字符</para>
/// <para>默认生成 8 位</para>
/// </summary>
/// <returns></returns>
public static string NextID()
{
return NextID(new GenerationOptions
{
UseNumbers = true,
UseSpecialCharacters = false,
Length = 8
});
}
/// <summary>
/// 生成短 ID
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public static string NextID(GenerationOptions options)
{
// 配置必填
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
// 判断生成的长度是否小于规定的长度,规定为 8
if (options.Length < Constants.MinimumAutoLength)
{
throw new ArgumentException(
$"The specified length of {options.Length} is less than the lower limit of {Constants.MinimumAutoLength} to avoid conflicts.");
}
var characterPool = _pool;
var poolBuilder = new StringBuilder(characterPool);
// 是否包含数字
if (options.UseNumbers)
{
poolBuilder.Append(Numbers);
}
// 是否包含特殊字符
if (options.UseSpecialCharacters)
{
poolBuilder.Append(Specials);
}
var pool = poolBuilder.ToString();
// 生成拼接
var output = new char[options.Length];
for (var i = 0; i < options.Length; i++)
{
lock (ThreadLock)
{
var charIndex = _random.Next(0, pool.Length);
output[i] = pool[charIndex];
}
}
return new string(output);
}
/// <summary>
/// 设置参与运算的字符,最少 50 位
/// </summary>
/// <param name="characters"></param>
public static void SetCharacters(string characters)
{
if (string.IsNullOrWhiteSpace(characters))
{
throw new ArgumentException("The replacement characters must not be null or empty.");
}
var charSet = characters
.ToCharArray()
.Where(x => !char.IsWhiteSpace(x))
.Distinct()
.ToArray();
if (charSet.Length < Constants.MinimumCharacterSetLength)
{
throw new InvalidOperationException(
$"The replacement characters must be at least {Constants.MinimumCharacterSetLength} letters in length and without whitespace.");
}
lock (ThreadLock)
{
_pool = new string(charSet);
}
}
/// <summary>
/// 设置种子步长
/// </summary>
/// <param name="seed"></param>
public static void SetSeed(int seed)
{
lock (ThreadLock)
{
_random = new Random(seed);
}
}
/// <summary>
/// 重置所有配置
/// </summary>
public static void Reset()
{
lock (ThreadLock)
{
_random = new Random();
_pool = $"{Smalls}{Bigs}";
}
}
}
}