BSON id 生成器的 C# 实现?

标签 c# .net mongodb bson

有谁知道是否存在 BSON ID 生成器的现有 c# 实现?

我需要在 .NET 客户端上生成 Mongodb objectID,但无法使用外部 dll,因此需要在代码中完成。我在谷歌上找不到任何东西,所以可能最终不得不自己写,但我想先和其他人核实一下。

谢谢。

最佳答案

您可以简单地复制 implementation如果您不允许引用该包,请添加到您的代码库。下面是它的简化版本。

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Security;
using System.Threading;

public struct ObjectId
{
    private static readonly ObjectId __emptyInstance = default(ObjectId);
    private static readonly int __staticMachine = (GetMachineHash() + GetAppDomainId()) & 0x00ffffff;
    private static readonly short __staticPid = GetPid();
    private static int __staticIncrement = new Random().Next();
    private static readonly DateTime __unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    private readonly int _a;
    private readonly int _b;
    private readonly int _c;

    private ObjectId(int timestamp, int machine, short pid, int increment)
    {
        _a = timestamp;
        _b = (machine << 8) | ((pid >> 8) & 0xff);
        _c = (pid << 24) | increment;
    }

    public static ObjectId GenerateNewId()
    {
        return GenerateNewId(GetTimestampFromDateTime(DateTime.UtcNow));
    }

    public static ObjectId GenerateNewId(int timestamp)
    {
        var increment = Interlocked.Increment(ref __staticIncrement) & 0x00ffffff; // only use low order 3 bytes
        return new ObjectId(timestamp, __staticMachine, __staticPid, increment);
    }

    private static int GetAppDomainId()
    {
        return AppDomain.CurrentDomain.Id;
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static int GetCurrentProcessId()
    {
        return Process.GetCurrentProcess().Id;
    }

    private static int GetMachineHash()
    {
        var machineName = GetMachineName();
        return 0x00ffffff & machineName.GetHashCode(); // use first 3 bytes of hash
    }

    private static string GetMachineName()
    {
        return Environment.MachineName;
    }

    private static short GetPid()
    {
        try
        {
            return (short) GetCurrentProcessId(); // use low order two bytes only
        }
        catch (SecurityException)
        {
            return 0;
        }
    }

    private static int GetTimestampFromDateTime(DateTime timestamp)
    {
        var secondsSinceEpoch = (long) Math.Floor((ToUniversalTime(timestamp) - __unixEpoch).TotalSeconds);
        if (secondsSinceEpoch < int.MinValue || secondsSinceEpoch > int.MaxValue)
            throw new ArgumentOutOfRangeException("timestamp");
        return (int) secondsSinceEpoch;
    }

    public override string ToString()
    {
        var c = new char[24];
        c[0] = ToHexChar((_a >> 28) & 0x0f);
        c[1] = ToHexChar((_a >> 24) & 0x0f);
        c[2] = ToHexChar((_a >> 20) & 0x0f);
        c[3] = ToHexChar((_a >> 16) & 0x0f);
        c[4] = ToHexChar((_a >> 12) & 0x0f);
        c[5] = ToHexChar((_a >> 8) & 0x0f);
        c[6] = ToHexChar((_a >> 4) & 0x0f);
        c[7] = ToHexChar(_a & 0x0f);
        c[8] = ToHexChar((_b >> 28) & 0x0f);
        c[9] = ToHexChar((_b >> 24) & 0x0f);
        c[10] = ToHexChar((_b >> 20) & 0x0f);
        c[11] = ToHexChar((_b >> 16) & 0x0f);
        c[12] = ToHexChar((_b >> 12) & 0x0f);
        c[13] = ToHexChar((_b >> 8) & 0x0f);
        c[14] = ToHexChar((_b >> 4) & 0x0f);
        c[15] = ToHexChar(_b & 0x0f);
        c[16] = ToHexChar((_c >> 28) & 0x0f);
        c[17] = ToHexChar((_c >> 24) & 0x0f);
        c[18] = ToHexChar((_c >> 20) & 0x0f);
        c[19] = ToHexChar((_c >> 16) & 0x0f);
        c[20] = ToHexChar((_c >> 12) & 0x0f);
        c[21] = ToHexChar((_c >> 8) & 0x0f);
        c[22] = ToHexChar((_c >> 4) & 0x0f);
        c[23] = ToHexChar(_c & 0x0f);
        return new string(c);
    }

    private static char ToHexChar(int value)
    {
        return (char) (value + (value < 10 ? '0' : 'a' - 10));
    }

    private static DateTime ToUniversalTime(DateTime dateTime)
    {
        if (dateTime == DateTime.MinValue)
            return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
        if (dateTime == DateTime.MaxValue)
            return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
        return dateTime.ToUniversalTime();
    }
}

关于BSON id 生成器的 C# 实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47349803/

相关文章:

c# - 如何在xaml/c#中旋转图像

c# - .Net SMTP 队列

c# regex 和 [] expression ,为什么 [+*/-] 无法解析?

javascript - 是否可以在不插入新 _id 的情况下创建新新闻? ( Mongoose )

单机上的 MongoDB 副本集

c# - NServiceBus,多个接口(interface)时按接口(interface)订阅

c# - 如何将 WebGrid 列的 int 值转换为字符串?

c# - 如何从 WEB API 请求和响应 XML 中删除命名空间?

c# - 无法将运算符 '<' 应用于类型 T 和 T 的操作数

mongodb - 如何通过 Java 驱动程序使用 Mongodb 批量更新?