代码之家  ›  专栏  ›  技术社区  ›  UpTheCreek

BSON id生成器的C#实现?

  •  1
  • UpTheCreek  · 技术社区  · 7 年前

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

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

    谢谢

    1 回复  |  直到 7 年前
        1
  •  4
  •   Andrii Litvinov    7 年前

    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();
        }
    }