Skip to content

Commit f593352

Browse files
committedMar 4, 2016
* Added support for configsection
* GetMachineSpecificGenerator & GetThreadSpecificGenerator renamed to CreateMachineSpecificGenerator & CreateThreadSpecificGenerator respectively to better convey that each invocation creates a new instance. * Explicitly check for negative generator-id's
1 parent 6b964e0 commit f593352

12 files changed

+235
-35
lines changed
 

‎IdGen.nuspec

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<metadata>
44
<id>IdGen</id>
55
<title>IdGen</title>
6-
<version>1.2.0</version>
6+
<version>1.3.0</version>
77
<authors>RobIII</authors>
88
<owners>RobIII</owners>
99
<projectUrl>https://github.com/RobThree/IdGen</projectUrl>
@@ -16,7 +16,8 @@
1616
A library that provides a decentralized, k-ordered id generation
1717
</summary>
1818
<releaseNotes>
19-
* GetMachineSpecificGenerator() and GetThreadSpecificGenerator() didn't use the GeneratorIdBits as bitmask resulting in incorrect generator ID's
19+
* Added config file support
20+
* GetMachineSpecificGenerator &amp; GetThreadSpecificGenerator renamed to CreateMachineSpecificGenerator &amp; CreateThreadSpecificGenerator respectively to better convey that each invokation creates a new instance.
2021
</releaseNotes>
2122
<tags>scalable unique id generator distributed</tags>
2223
</metadata>
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System;
2+
using System.Configuration;
3+
using System.Globalization;
4+
5+
namespace IdGen.Configuration
6+
{
7+
/// <summary>
8+
/// Represents an IdGenerator configuration element. This class cannot be inherited.
9+
/// </summary>
10+
public sealed class IdGeneratorElement : ConfigurationElement
11+
{
12+
private readonly string[] DATETIMEFORMATS = { "yyyy-MM-dd\\THH:mm:ss", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd" };
13+
14+
/// <summary>
15+
/// Gets/sets the name of the <see cref="IdGeneratorElement"/>.
16+
/// </summary>
17+
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
18+
public string Name
19+
{
20+
get { return (string)this["name"]; }
21+
set { this["name"] = value; }
22+
}
23+
24+
/// <summary>
25+
/// Gets/sets the GeneratorId of the <see cref="IdGeneratorElement"/>.
26+
/// </summary>
27+
[ConfigurationProperty("id", IsRequired = true)]
28+
public int Id
29+
{
30+
get { return (int)this["id"]; }
31+
set { this["id"] = value; }
32+
}
33+
34+
35+
[ConfigurationProperty("epoch", IsRequired = true)]
36+
private string stringepoch
37+
{
38+
get { return (string)this["epoch"]; }
39+
set { this["epoch"] = value; }
40+
}
41+
42+
/// <summary>
43+
/// Gets/sets the Epoch of the <see cref="IdGeneratorElement"/>.
44+
/// </summary>
45+
public DateTime Epoch
46+
{
47+
get { return DateTime.SpecifyKind(DateTime.ParseExact(this.stringepoch, DATETIMEFORMATS, CultureInfo.InvariantCulture, DateTimeStyles.None), DateTimeKind.Utc); }
48+
set { this.stringepoch = value.ToString(DATETIMEFORMATS[0]); }
49+
}
50+
51+
/// <summary>
52+
/// Gets/sets the <see cref="MaskConfig.TimestampBits"/> of the <see cref="IdGeneratorElement"/>.
53+
/// </summary>
54+
[ConfigurationProperty("timestampBits", IsRequired = true)]
55+
public byte TimestampBits
56+
{
57+
get { return (byte)this["timestampBits"]; }
58+
set { this["timestampBits"] = value; }
59+
}
60+
61+
/// <summary>
62+
/// Gets/sets the <see cref="MaskConfig.GeneratorIdBits"/> of the <see cref="IdGeneratorElement"/>.
63+
/// </summary>
64+
[ConfigurationProperty("generatorIdBits", IsRequired = true)]
65+
public byte GeneratorIdBits
66+
{
67+
get { return (byte)this["generatorIdBits"]; }
68+
set { this["generatorIdBits"] = value; }
69+
}
70+
71+
/// <summary>
72+
/// Gets/sets the <see cref="MaskConfig.SequenceBits"/> of the <see cref="IdGeneratorElement"/>.
73+
/// </summary>
74+
[ConfigurationProperty("sequenceBits", IsRequired = true)]
75+
public byte SequenceBits
76+
{
77+
get { return (byte)this["sequenceBits"]; }
78+
set { this["sequenceBits"] = value; }
79+
}
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Configuration;
2+
3+
namespace IdGen.Configuration
4+
{
5+
/// <summary>
6+
/// Represents a IdGenerators configuration element containing a collection of child elements.
7+
/// </summary>
8+
public class IdGeneratorsCollection : ConfigurationElementCollection
9+
{
10+
/// <summary>
11+
/// Creates a new <see cref="IdGeneratorElement"/>.
12+
/// </summary>
13+
/// <returns>A newly created <see cref="IdGeneratorElement"/>.</returns>
14+
protected override ConfigurationElement CreateNewElement()
15+
{
16+
return new IdGeneratorElement();
17+
}
18+
19+
/// <summary>
20+
/// Gets the element key for a specified <see cref="IdGeneratorElement"/>.
21+
/// </summary>
22+
/// <param name="element">The <see cref="IdGeneratorElement"/> to return the key for.</param>
23+
/// <returns>An <see cref="System.Object"/> that acts as the key for the specified <see cref="IdGeneratorElement"/>.</returns>
24+
protected override object GetElementKey(ConfigurationElement element)
25+
{
26+
return ((IdGeneratorElement)element).Name;
27+
}
28+
}
29+
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Configuration;
2+
3+
namespace IdGen.Configuration
4+
{
5+
/// <summary>
6+
/// Represents an IdGenerators section within a configuration file.
7+
/// </summary>
8+
public class IdGeneratorsSection : ConfigurationSection
9+
{
10+
/// <summary>
11+
/// The default name of the section.
12+
/// </summary>
13+
public const string SectionName = "idGenSection";
14+
15+
/// <summary>
16+
/// The default name of the collection.
17+
/// </summary>
18+
private const string IdGensCollectionName = "idGenerators";
19+
20+
/// <summary>
21+
/// Gets an <see cref="IdGeneratorsCollection"/> of all the <see cref="IdGeneratorElement"/> objects in all
22+
/// participating configuration files.
23+
/// </summary>
24+
[ConfigurationProperty(IdGensCollectionName)]
25+
[ConfigurationCollection(typeof(IdGeneratorsCollection), AddItemName = "idGenerator")]
26+
public IdGeneratorsCollection IdGenerators { get { return (IdGeneratorsCollection)base[IdGensCollectionName]; } }
27+
}
28+
}

‎IdGen/IdGen.csproj

+6
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@
3535
</PropertyGroup>
3636
<ItemGroup>
3737
<Reference Include="System" />
38+
<Reference Include="System.configuration" />
3839
<Reference Include="System.Core" />
3940
<Reference Include="Microsoft.CSharp" />
4041
</ItemGroup>
4142
<ItemGroup>
43+
<Compile Include="Configuration\IdGeneratorsSection.cs" />
44+
<Compile Include="Configuration\IdGeneratorsCollection.cs" />
4245
<Compile Include="DefaultTimeSource.cs" />
4346
<Compile Include="IdGenerator.cs" />
4447
<Compile Include="IIdGenerator.cs" />
@@ -48,6 +51,9 @@
4851
<Compile Include="Properties\AssemblyInfo.cs" />
4952
<Compile Include="SequenceOverflowException.cs" />
5053
</ItemGroup>
54+
<ItemGroup>
55+
<Compile Include="Configuration\IdGeneratorElement.cs" />
56+
</ItemGroup>
5157
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
5258
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
5359
Other similar extension points exist, see Microsoft.Common.targets.

‎IdGen/IdGenerator.cs

+68-20
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
using System;
1+
using IdGen.Configuration;
2+
using System;
3+
using System.Linq;
24
using System.Collections;
35
using System.Collections.Generic;
6+
using System.Configuration;
47
using System.Runtime.CompilerServices;
58
using System.Threading;
9+
using System.Collections.Concurrent;
610

711
namespace IdGen
812
{
@@ -13,6 +17,7 @@ public class IdGenerator : IIdGenerator<long>
1317
{
1418
private static readonly DateTime defaultepoch = new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc);
1519
private static readonly ITimeSource defaulttimesource = new DefaultTimeSource();
20+
private static readonly ConcurrentDictionary<string, IdGenerator> _namedgenerators = new ConcurrentDictionary<string, IdGenerator>();
1621

1722
private int _sequence = 0;
1823
private long _lastgen = -1;
@@ -123,7 +128,7 @@ public IdGenerator(int generatorId, DateTime epoch, MaskConfig maskConfig, ITime
123128
MASK_GENERATOR = GetMask(maskConfig.GeneratorIdBits);
124129
MASK_SEQUENCE = GetMask(maskConfig.SequenceBits);
125130

126-
if (generatorId > MASK_GENERATOR)
131+
if (generatorId < 0 || generatorId > MASK_GENERATOR)
127132
throw new ArgumentOutOfRangeException(string.Format("GeneratorId must be between 0 and {0} (inclusive).", MASK_GENERATOR));
128133

129134
SHIFT_TIME = maskConfig.GeneratorIdBits + maskConfig.SequenceBits;
@@ -173,52 +178,95 @@ public long CreateId()
173178
}
174179
}
175180

181+
/// <summary>
182+
/// Returns an instance of an <see cref="IdGenerator"/> based on the values in the corresponding idGenerator
183+
/// element in the idGenSection of the configuration file. The <see cref="DefaultTimeSource"/> is used to
184+
/// retrieve timestamp information.
185+
/// </summary>
186+
/// <param name="name">The name of the <see cref="IdGenerator"/> in the idGenSection.</param>
187+
/// <returns>An instance of an <see cref="IdGenerator"/> based on the values in the corresponding idGenerator
188+
/// element in the idGenSection of the configuration file.</returns>
189+
/// <remarks>
190+
/// When the <see cref="IdGenerator"/> doesn't exist it is created; any consequent calls to this method with
191+
/// the same name will return the same instance.
192+
/// </remarks>
193+
public static IdGenerator GetFromConfig(string name)
194+
{
195+
return GetFromConfig(name, defaulttimesource);
196+
}
197+
198+
/// <summary>
199+
/// Returns an instance of an <see cref="IdGenerator"/> based on the values in the corresponding idGenerator
200+
/// element in the idGenSection of the configuration file.
201+
/// </summary>
202+
/// <param name="name">The name of the <see cref="IdGenerator"/> in the idGenSection.</param>
203+
/// <param name="timeSource">The time-source to use when acquiring time data.</param>
204+
/// <returns>An instance of an <see cref="IdGenerator"/> based on the values in the corresponding idGenerator
205+
/// element in the idGenSection of the configuration file.</returns>
206+
/// <remarks>
207+
/// When the <see cref="IdGenerator"/> doesn't exist it is created; any consequent calls to this method with
208+
/// the same name will return the same instance.
209+
/// </remarks>
210+
public static IdGenerator GetFromConfig(string name, ITimeSource timeSource)
211+
{
212+
var result = _namedgenerators.GetOrAdd(name, (n) =>
213+
{
214+
var idgenerators = (ConfigurationManager.GetSection(IdGeneratorsSection.SectionName) as IdGeneratorsSection).IdGenerators;
215+
var idgen = idgenerators.OfType<IdGeneratorElement>().FirstOrDefault(e => e.Name.Equals(n));
216+
if (idgen != null)
217+
return new IdGenerator(idgen.Id, idgen.Epoch, new MaskConfig(idgen.TimestampBits, idgen.GeneratorIdBits, idgen.SequenceBits), timeSource);
218+
throw new KeyNotFoundException();
219+
});
220+
221+
return result;
222+
}
223+
176224
/// <summary>
177225
/// Returns a new instance of an <see cref="IdGenerator"/> based on the machine-name.
178226
/// </summary>
179-
/// <returns>A new instance of an <see cref="IdGenerator"/> based on the machine-name</returns>
227+
/// <returns>A new instance of an <see cref="IdGenerator"/> based on the machine-name.</returns>
180228
/// <remarks>
181229
/// Note: be very careful using this method; it is recommended to explicitly set an generatorId instead since
182230
/// a hash of the machinename could result in a collision (especially when the bitmask for the generator is
183231
/// very small) of the generator-id's across machines. Only use this in small setups (few hosts) and if you have
184232
/// no other choice. Prefer to specify generator id's via configuration file or other means instead.
185233
/// </remarks>
186-
public static IdGenerator GetMachineSpecificGenerator()
234+
public static IdGenerator CreateMachineSpecificGenerator()
187235
{
188-
return GetMachineSpecificGenerator(defaultepoch);
236+
return CreateMachineSpecificGenerator(defaultepoch);
189237
}
190238

191239
/// <summary>
192240
/// Returns a new instance of an <see cref="IdGenerator"/> based on the machine-name.
193241
/// </summary>
194242
/// <param name="epoch">The Epoch of the generator.</param>
195-
/// <returns>A new instance of an <see cref="IdGenerator"/> based on the machine-name</returns>
243+
/// <returns>A new instance of an <see cref="IdGenerator"/> based on the machine-name.</returns>
196244
/// <remarks>
197245
/// Note: be very careful using this method; it is recommended to explicitly set an generatorId instead since
198246
/// a hash of the machinename could result in a collision (especially when the bitmask for the generator is
199247
/// very small) of the generator-id's across machines. Only use this in small setups (few hosts) and if you have
200248
/// no other choice. Prefer to specify generator id's via configuration file or other means instead.
201249
/// </remarks>
202-
public static IdGenerator GetMachineSpecificGenerator(DateTime epoch)
250+
public static IdGenerator CreateMachineSpecificGenerator(DateTime epoch)
203251
{
204-
return GetMachineSpecificGenerator(epoch, MaskConfig.Default);
252+
return CreateMachineSpecificGenerator(epoch, MaskConfig.Default);
205253
}
206254

207255
/// <summary>
208256
/// Returns a new instance of an <see cref="IdGenerator"/> based on the machine-name.
209257
/// </summary>
210258
/// <param name="epoch">The Epoch of the generator.</param>
211259
/// <param name="maskConfig">The <see cref="MaskConfig"/> of the generator.</param>
212-
/// <returns>A new instance of an <see cref="IdGenerator"/> based on the machine-name</returns>
260+
/// <returns>A new instance of an <see cref="IdGenerator"/> based on the machine-name.</returns>
213261
/// <remarks>
214262
/// Note: be very careful using this method; it is recommended to explicitly set an generatorId instead since
215263
/// a hash of the machinename could result in a collision (especially when the bitmask for the generator is
216264
/// very small) of the generator-id's across machines. Only use this in small setups (few hosts) and if you have
217265
/// no other choice. Prefer to specify generator id's via configuration file or other means instead.
218266
/// </remarks>
219-
public static IdGenerator GetMachineSpecificGenerator(DateTime epoch, MaskConfig maskConfig)
267+
public static IdGenerator CreateMachineSpecificGenerator(DateTime epoch, MaskConfig maskConfig)
220268
{
221-
return GetMachineSpecificGenerator(epoch, maskConfig, defaulttimesource);
269+
return CreateMachineSpecificGenerator(epoch, maskConfig, defaulttimesource);
222270
}
223271

224272
/// <summary>
@@ -227,14 +275,14 @@ public static IdGenerator GetMachineSpecificGenerator(DateTime epoch, MaskConfig
227275
/// <param name="epoch">The Epoch of the generator.</param>
228276
/// <param name="maskConfig">The <see cref="MaskConfig"/> of the generator.</param>
229277
/// <param name="timeSource">The time-source to use when acquiring time data.</param>
230-
/// <returns>A new instance of an <see cref="IdGenerator"/> based on the machine-name</returns>
278+
/// <returns>A new instance of an <see cref="IdGenerator"/> based on the machine-name.</returns>
231279
/// <remarks>
232280
/// Note: be very careful using this method; it is recommended to explicitly set an generatorId instead since
233281
/// a hash of the machinename could result in a collision (especially when the bitmask for the generator is
234282
/// very small) of the generator-id's across machines. Only use this in small setups (few hosts) and if you have
235283
/// no other choice. Prefer to specify generator id's via configuration file or other means instead.
236284
/// </remarks>
237-
public static IdGenerator GetMachineSpecificGenerator(DateTime epoch, MaskConfig maskConfig, ITimeSource timeSource)
285+
public static IdGenerator CreateMachineSpecificGenerator(DateTime epoch, MaskConfig maskConfig, ITimeSource timeSource)
238286
{
239287
return new IdGenerator(GetMachineHash() & (int)GetMask(maskConfig.GeneratorIdBits), epoch, maskConfig, timeSource);
240288
}
@@ -248,9 +296,9 @@ public static IdGenerator GetMachineSpecificGenerator(DateTime epoch, MaskConfig
248296
/// if this method is used across machines there's a high probability of collisions in generator-id's. In that
249297
/// case prefer to explicitly set the generator id's via configuration file or other means instead.
250298
/// </remarks>
251-
public static IdGenerator GetThreadSpecificGenerator()
299+
public static IdGenerator CreateThreadSpecificGenerator()
252300
{
253-
return GetThreadSpecificGenerator(defaultepoch);
301+
return CreateThreadSpecificGenerator(defaultepoch);
254302
}
255303

256304
/// <summary>
@@ -263,9 +311,9 @@ public static IdGenerator GetThreadSpecificGenerator()
263311
/// if this method is used across machines there's a high probability of collisions in generator-id's. In that
264312
/// case prefer to explicitly set the generator id's via configuration file or other means instead.
265313
/// </remarks>
266-
public static IdGenerator GetThreadSpecificGenerator(DateTime epoch)
314+
public static IdGenerator CreateThreadSpecificGenerator(DateTime epoch)
267315
{
268-
return GetThreadSpecificGenerator(epoch, MaskConfig.Default);
316+
return CreateThreadSpecificGenerator(epoch, MaskConfig.Default);
269317
}
270318

271319
/// <summary>
@@ -279,9 +327,9 @@ public static IdGenerator GetThreadSpecificGenerator(DateTime epoch)
279327
/// if this method is used across machines there's a high probability of collisions in generator-id's. In that
280328
/// case prefer to explicitly set the generator id's via configuration file or other means instead.
281329
/// </remarks>
282-
public static IdGenerator GetThreadSpecificGenerator(DateTime epoch, MaskConfig maskConfig)
330+
public static IdGenerator CreateThreadSpecificGenerator(DateTime epoch, MaskConfig maskConfig)
283331
{
284-
return GetThreadSpecificGenerator(epoch, maskConfig, defaulttimesource);
332+
return CreateThreadSpecificGenerator(epoch, maskConfig, defaulttimesource);
285333
}
286334

287335
/// <summary>
@@ -296,7 +344,7 @@ public static IdGenerator GetThreadSpecificGenerator(DateTime epoch, MaskConfig
296344
/// if this method is used across machines there's a high probability of collisions in generator-id's. In that
297345
/// case prefer to explicitly set the generator id's via configuration file or other means instead.
298346
/// </remarks>
299-
public static IdGenerator GetThreadSpecificGenerator(DateTime epoch, MaskConfig maskConfig, ITimeSource timeSource)
347+
public static IdGenerator CreateThreadSpecificGenerator(DateTime epoch, MaskConfig maskConfig, ITimeSource timeSource)
300348
{
301349
return new IdGenerator(GetThreadId() & (int)GetMask(maskConfig.GeneratorIdBits), epoch, maskConfig, timeSource);
302350
}

‎IdGen/Properties/AssemblyInfo.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@
3131
// You can specify all the values or you can default the Build and Revision Numbers
3232
// by using the '*' as shown below:
3333
// [assembly: AssemblyVersion("1.0.*")]
34-
[assembly: AssemblyVersion("1.2.0.0")]
35-
[assembly: AssemblyFileVersion("1.2.0.0")]
34+
[assembly: AssemblyVersion("1.3.0.0")]
35+
[assembly: AssemblyFileVersion("1.3.0.0")]

‎IdGenDocumentation/Content/Welcome.aml

+3-3
Original file line numberDiff line numberDiff line change
@@ -220,19 +220,19 @@
220220
All properties are read-only to prevent changes once an <codeEntityReference linkText="IdGenerator">T:IdGen.IdGenerator</codeEntityReference> has been instantiated.
221221
</para>
222222
<para>
223-
The <codeEntityReference linkText="IdGenerator">T:IdGen.IdGenerator</codeEntityReference> class provides two 'factory methods' to quickly create a <codeEntityReference linkText="machine-specific">M:IdGen.IdGenerator.GetMachineSpecificGenerator</codeEntityReference> (based on the hostname) or <codeEntityReference linkText="thread-specific">M:IdGen.IdGenerator.GetThreadSpecificGenerator</codeEntityReference> IdGenerator:
223+
The <codeEntityReference linkText="IdGenerator">T:IdGen.IdGenerator</codeEntityReference> class provides two 'factory methods' to quickly create a <codeEntityReference linkText="machine-specific">M:IdGen.IdGenerator.CreateMachineSpecificGenerator</codeEntityReference> (based on the hostname) or <codeEntityReference linkText="thread-specific">M:IdGen.IdGenerator.CreateThreadSpecificGenerator</codeEntityReference> IdGenerator:
224224
</para>
225225
<code language="cs">
226226
<![CDATA[
227-
var generator = IdGenerator.GetMachineSpecificGenerator();
227+
var generator = IdGenerator.CreateMachineSpecificGenerator();
228228
]]>
229229
</code>
230230
<para>
231231
or:
232232
</para>
233233
<code language="cs">
234234
<![CDATA[
235-
var generator = IdGenerator.GetThreadSpecificGenerator();
235+
var generator = IdGenerator.CreateThreadSpecificGenerator();
236236
]]>
237237
</code>
238238
<para>

‎IdGenDocumentation/IdGenDocumentation.shfbproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@
6060
<CppCommentsFixup>False</CppCommentsFixup>
6161
<CleanIntermediates>True</CleanIntermediates>
6262
<NamespaceSummaries>
63-
<NamespaceSummaryItem name="IdGen" isDocumented="True" xmlns="">&lt;para&gt;The IdGen namespace contains classes that allow generating unique (distributed) ID's.&lt;/para&gt;</NamespaceSummaryItem>
64-
</NamespaceSummaries>
63+
<NamespaceSummaryItem name="IdGen" isDocumented="True">&lt;para&gt;The IdGen namespace contains classes that allow generating unique (distributed) ID's.&lt;/para&gt;</NamespaceSummaryItem>
64+
<NamespaceSummaryItem name="IdGen.Configuration" isDocumented="True">&lt;para&gt;The IdGen.Configuration namespace contains the types that provide the programming model for handling configuration data.&lt;/para&gt;</NamespaceSummaryItem></NamespaceSummaries>
6565
<HelpFileVersion>1.2.0.0</HelpFileVersion>
6666
<PlugInNamespaces>ms.vsipcc+, ms.vsexpresscc+</PlugInNamespaces>
6767
<CollectionTocStyle>Hierarchical</CollectionTocStyle>

‎IdGenTests/IdGenTests.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -224,21 +224,21 @@ public void Constructor_Throws_OnTimestampWraparound()
224224
}
225225

226226
[TestMethod]
227-
public void GetMachineSpecificGenerator_Returns_IdGenerator()
227+
public void CreateMachineSpecificGenerator_Returns_IdGenerator()
228228
{
229-
var g = IdGenerator.GetMachineSpecificGenerator();
229+
var g = IdGenerator.CreateMachineSpecificGenerator();
230230
Assert.IsNotNull(g);
231231
}
232232

233233
[TestMethod]
234-
public void GetThreadSpecificGenerator_Returns_IdGenerator()
234+
public void CreateThreadSpecificGenerator_Returns_IdGenerator()
235235
{
236236
if (Environment.ProcessorCount > 1)
237237
{
238238
const int gcount = 100; //Create a fair amount of generators
239239
var tasks = new Task<IdGenerator>[gcount];
240240
for (int i = 0; i < gcount; i++)
241-
tasks[i] = Task.Run(() => IdGenerator.GetThreadSpecificGenerator());
241+
tasks[i] = Task.Run(() => IdGenerator.CreateThreadSpecificGenerator());
242242
Task.WaitAll(tasks);
243243

244244
// Get all unique generator ID's in an array

‎IdGenTests/IdGenTests.csproj

+7
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
</Otherwise>
5151
</Choose>
5252
<ItemGroup>
53+
<Compile Include="ConfigTests.cs" />
5354
<Compile Include="IdGenTests.cs" />
5455
<Compile Include="MaskConfigTests.cs" />
5556
<Compile Include="MockTimeSource.cs" />
@@ -61,6 +62,12 @@
6162
<Name>IdGen</Name>
6263
</ProjectReference>
6364
</ItemGroup>
65+
<ItemGroup>
66+
<None Include="App.config">
67+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
68+
<SubType>Designer</SubType>
69+
</None>
70+
</ItemGroup>
6471
<Choose>
6572
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
6673
<ItemGroup>

‎README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,11 @@ All properties are read-only to prevent changes once an `IdGenerator` has been i
125125

126126
The `IdGenerator` class provides two 'factory methods' to quickly create a machine-specific (based on the hostname) or thread-specific `IdGenerator`:
127127

128-
`var generator = IdGenerator.GetMachineSpecificGenerator();`
128+
`var generator = IdGenerator.CreateMachineSpecificGenerator();`
129129

130130
or:
131131

132-
`var generator = IdGenerator.GetThreadSpecificGenerator();`
132+
`var generator = IdGenerator.CreateThreadSpecificGenerator();`
133133

134134
These methods (and their overloads that allow you to specify the epoch, `MaskConfig` and `TimeSource`) create an `IdGenerator` based on hostname or (managed) thread-id. However, it is recommended you explicitly set / configure a generator-id since these two methods could cause 'collisions' when machinenames' hashes result in the same id's or when thread-id's collide with thread-id's on other machines.
135135

0 commit comments

Comments
 (0)
Please sign in to comment.