2017-11-17 14 views
1

BSON IDジェネレータの既存のC#実装が存在するかどうかは知っていますか?BSON IDジェネレータのC#implementaion?

.NETクライアントでMongodbのobjectIDを生成する必要がありますが、外部のDLLを使用できないため、コードで実行する必要があります。私はGoogle上で何かを見つけることができなかったので、おそらく自分自身を書く必要がなくなりますが、他人と最初に確認したいと思っていました。

ありがとうございました。

答えて

4

パッケージを参照することができない場合は、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(); 
    } 
} 
+0

ありがとうございました。私はC#3に固執しているので、その実装を直接使用することはできません。私は最小値(新しいIDジェネレータのみ)を抽出しようとしましたが、これらのクラス間で多くの相互依存関係を実行するのは難しいです。 – UpTheCreek

+0

@UpTheCreek最小限の実装で私の答えを更新しました。しかし、私はC#3で利用できないものを使用するかどうかはわかりません。それが役に立てば幸い。 –

+1

おはよう、ありがとう! – UpTheCreek

関連する問題