forked from Meowv/Plus.Core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System; | ||
|
||
namespace Plus.Guids | ||
{ | ||
/// <summary> | ||
/// Used to generate Ids. | ||
/// </summary> | ||
public interface IGuidGenerator | ||
{ | ||
/// <summary> | ||
/// Creates a new <see cref="Guid"/>. | ||
/// </summary> | ||
Guid Create(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using Plus.Modularity; | ||
|
||
namespace Plus.Guids | ||
{ | ||
public class PlusGuidsModule : PlusModule | ||
{ | ||
|
||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
Plus.Core/Plus/Guids/PlusSequentialGuidGeneratorOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
namespace Plus.Guids | ||
{ | ||
public class PlusSequentialGuidGeneratorOptions | ||
{ | ||
/// <summary> | ||
/// Default value: null (unspecified). | ||
/// Use <see cref="GetDefaultSequentialGuidType"/> method | ||
/// to get the value on use, since it fall backs to a default value. | ||
/// </summary> | ||
public SequentialGuidType? DefaultSequentialGuidType { get; set; } | ||
|
||
/// <summary> | ||
/// Get the <see cref="DefaultSequentialGuidType"/> value | ||
/// or returns <see cref="SequentialGuidType.SequentialAtEnd"/> | ||
/// if <see cref="DefaultSequentialGuidType"/> was null. | ||
/// </summary> | ||
public SequentialGuidType GetDefaultSequentialGuidType() | ||
{ | ||
return DefaultSequentialGuidType ?? | ||
SequentialGuidType.SequentialAtEnd; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
using System; | ||
using System.Security.Cryptography; | ||
using Microsoft.Extensions.Options; | ||
using Plus.DependencyInjection; | ||
|
||
namespace Plus.Guids | ||
{ | ||
/* This code is taken from jhtodd/SequentialGuid https://github.com/jhtodd/SequentialGuid/blob/master/SequentialGuid/Classes/SequentialGuid.cs */ | ||
|
||
/// <summary> | ||
/// Implements <see cref="IGuidGenerator"/> by creating sequential Guids. | ||
/// Use <see cref="PlusSequentialGuidGeneratorOptions"/> to configure. | ||
/// </summary> | ||
public class SequentialGuidGenerator : IGuidGenerator, ITransientDependency | ||
{ | ||
public PlusSequentialGuidGeneratorOptions Options { get; } | ||
|
||
private static readonly RandomNumberGenerator RandomNumberGenerator = RandomNumberGenerator.Create(); | ||
|
||
public SequentialGuidGenerator(IOptions<PlusSequentialGuidGeneratorOptions> options) | ||
{ | ||
Options = options.Value; | ||
} | ||
|
||
public Guid Create() | ||
{ | ||
return Create(Options.GetDefaultSequentialGuidType()); | ||
} | ||
|
||
public Guid Create(SequentialGuidType guidType) | ||
{ | ||
// We start with 16 bytes of cryptographically strong random data. | ||
var randomBytes = new byte[10]; | ||
RandomNumberGenerator.GetBytes(randomBytes); | ||
|
||
// An alternate method: use a normally-created GUID to get our initial | ||
// random data: | ||
// byte[] randomBytes = Guid.NewGuid().ToByteArray(); | ||
// This is faster than using RNGCryptoServiceProvider, but I don't | ||
// recommend it because the .NET Framework makes no guarantee of the | ||
// randomness of GUID data, and future versions (or different | ||
// implementations like Mono) might use a different method. | ||
|
||
// Now we have the random basis for our GUID. Next, we need to | ||
// create the six-byte block which will be our timestamp. | ||
|
||
// We start with the number of milliseconds that have elapsed since | ||
// DateTime.MinValue. This will form the timestamp. There's no use | ||
// being more specific than milliseconds, since DateTime.Now has | ||
// limited resolution. | ||
|
||
// Using millisecond resolution for our 48-bit timestamp gives us | ||
// about 5900 years before the timestamp overflows and cycles. | ||
// Hopefully this should be sufficient for most purposes. :) | ||
long timestamp = DateTime.UtcNow.Ticks / 10000L; | ||
|
||
// Then get the bytes | ||
byte[] timestampBytes = BitConverter.GetBytes(timestamp); | ||
|
||
// Since we're converting from an Int64, we have to reverse on | ||
// little-endian systems. | ||
if (BitConverter.IsLittleEndian) | ||
{ | ||
Array.Reverse(timestampBytes); | ||
} | ||
|
||
byte[] guidBytes = new byte[16]; | ||
|
||
switch (guidType) | ||
{ | ||
case SequentialGuidType.SequentialAsString: | ||
case SequentialGuidType.SequentialAsBinary: | ||
|
||
// For string and byte-array version, we copy the timestamp first, followed | ||
// by the random data. | ||
Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); | ||
Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); | ||
|
||
// If formatting as a string, we have to compensate for the fact | ||
// that .NET regards the Data1 and Data2 block as an Int32 and an Int16, | ||
// respectively. That means that it switches the order on little-endian | ||
// systems. So again, we have to reverse. | ||
if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) | ||
{ | ||
Array.Reverse(guidBytes, 0, 4); | ||
Array.Reverse(guidBytes, 4, 2); | ||
} | ||
|
||
break; | ||
|
||
case SequentialGuidType.SequentialAtEnd: | ||
|
||
// For sequential-at-the-end versions, we copy the random data first, | ||
// followed by the timestamp. | ||
Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); | ||
Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); | ||
break; | ||
} | ||
|
||
return new Guid(guidBytes); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
namespace Plus.Guids | ||
{ | ||
/// <summary> | ||
/// Describes the type of a sequential GUID value. | ||
/// </summary> | ||
public enum SequentialGuidType | ||
{ | ||
/// <summary> | ||
/// The GUID should be sequential when formatted using the <see cref="Guid.ToString()" /> method. | ||
/// Used by MySql and PostgreSql. | ||
/// </summary> | ||
SequentialAsString, | ||
|
||
/// <summary> | ||
/// The GUID should be sequential when formatted using the <see cref="Guid.ToByteArray" /> method. | ||
/// Used by Oracle. | ||
/// </summary> | ||
SequentialAsBinary, | ||
|
||
/// <summary> | ||
/// The sequential portion of the GUID should be located at the end of the Data4 block. | ||
/// Used by SqlServer. | ||
/// </summary> | ||
SequentialAtEnd | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
|
||
namespace Plus.Guids | ||
{ | ||
/// <summary> | ||
/// Implements <see cref="IGuidGenerator"/> by using <see cref="Guid.NewGuid"/>. | ||
/// </summary> | ||
public class SimpleGuidGenerator : IGuidGenerator | ||
{ | ||
public static SimpleGuidGenerator Instance { get; } = new SimpleGuidGenerator(); | ||
|
||
public virtual Guid Create() | ||
{ | ||
return Guid.NewGuid(); | ||
} | ||
} | ||
} |