Commit 13dce8c
Changed files (10)
product
Gorilla.Commons.Infrastructure
product/Gorilla.Commons.Infrastructure/Transactions/Context.cs
@@ -6,9 +6,9 @@ namespace Gorilla.Commons.Infrastructure.Transactions
{
readonly IDictionary items;
- public Context() : this(new Hashtable())
- {
- }
+ //public Context() : this(new Hashtable())
+ //{
+ //}
public Context(IDictionary items)
{
product/Gorilla.Commons.Infrastructure/Transactions/ContextFactory.cs
@@ -0,0 +1,15 @@
+namespace Gorilla.Commons.Infrastructure.Transactions
+{
+ public interface IContextFactory
+ {
+ IContext create_for(IScopedStorage storage);
+ }
+
+ public class ContextFactory : IContextFactory
+ {
+ public IContext create_for(IScopedStorage storage)
+ {
+ return new Context(storage.provide_storage());
+ }
+ }
+}
\ No newline at end of file
product/Gorilla.Commons.Infrastructure/Transactions/ContextFactorySpecs.cs
@@ -0,0 +1,30 @@
+using System.Collections;
+using developwithpassion.bdd.contexts;
+using Gorilla.Commons.Testing;
+
+namespace Gorilla.Commons.Infrastructure.Transactions
+{
+ public class ContextFactorySpecs
+ {
+ }
+
+ public class when_creating_a_new_context : concerns_for<IContextFactory, ContextFactory>
+ {
+ context c = () =>
+ {
+ scope = an<IScopedStorage>();
+ storage = an<IDictionary>();
+
+ when_the(scope).is_told_to(x => x.provide_storage()).it_will_return(storage);
+ };
+
+ because b = () => { result = sut.create_for(scope); };
+
+ it should_return_a_context_that_represents_the_specified_scope =
+ () => result.should_be_an_instance_of<Context>();
+
+ static IDictionary storage;
+ static IScopedStorage scope;
+ static IContext result;
+ }
+}
\ No newline at end of file
product/Gorilla.Commons.Infrastructure/Transactions/IScopedStorage.cs
@@ -0,0 +1,9 @@
+using System.Collections;
+
+namespace Gorilla.Commons.Infrastructure.Transactions
+{
+ public interface IScopedStorage
+ {
+ IDictionary provide_storage();
+ }
+}
\ No newline at end of file
product/Gorilla.Commons.Infrastructure/Transactions/IThread.cs
@@ -0,0 +1,7 @@
+namespace Gorilla.Commons.Infrastructure.Transactions
+{
+ public interface IThread
+ {
+ T provide_slot_for<T>() where T : new();
+ }
+}
\ No newline at end of file
product/Gorilla.Commons.Infrastructure/Transactions/PerThread.cs
@@ -37,17 +37,17 @@ namespace Gorilla.Commons.Infrastructure.Transactions
IDictionary get_items()
{
- var id = Thread.CurrentThread.ManagedThreadId;
+ var id = System.Threading.Thread.CurrentThread.ManagedThreadId;
within_lock(() =>
{
if (!slots.ContainsKey(id))
{
- var slot = Thread.GetNamedDataSlot(GetType().FullName);
+ var slot = System.Threading.Thread.GetNamedDataSlot(GetType().FullName);
slots.Add(id, slot);
- Thread.SetData(slot, new Hashtable());
+ System.Threading.Thread.SetData(slot, new Hashtable());
}
});
- return (IDictionary) Thread.GetData(slots[id]);
+ return (IDictionary) System.Threading.Thread.GetData(slots[id]);
}
void within_lock(Action action)
product/Gorilla.Commons.Infrastructure/Transactions/PerThreadScopedStorage.cs
@@ -0,0 +1,19 @@
+using System.Collections;
+
+namespace Gorilla.Commons.Infrastructure.Transactions
+{
+ public class PerThreadScopedStorage : IScopedStorage
+ {
+ readonly IThread current_thread;
+
+ public PerThreadScopedStorage(IThread current_thread)
+ {
+ this.current_thread = current_thread;
+ }
+
+ public IDictionary provide_storage()
+ {
+ return current_thread.provide_slot_for<Hashtable>();
+ }
+ }
+}
\ No newline at end of file
product/Gorilla.Commons.Infrastructure/Transactions/PerThreadScopedStorageSpecs.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections;
+using developwithpassion.bdd.contexts;
+using Gorilla.Commons.Testing;
+
+namespace Gorilla.Commons.Infrastructure.Transactions
+{
+ public class PerThreadScopedStorageSpecs
+ {
+ }
+
+ public class when_retrieving_the_storage_for_a_specific_thread :
+ concerns_for<IScopedStorage, PerThreadScopedStorage>
+ {
+ context c = () =>
+ {
+ thread_id = DateTime.Now.Ticks;
+ thread = the_dependency<IThread>();
+ storage = new Hashtable();
+ when_the(thread)
+ .is_told_to(x => x.provide_slot_for<Hashtable>())
+ .it_will_return(storage);
+ };
+
+ because b = () => { result = sut.provide_storage(); };
+
+ it should_return_the_storage_the_corresponds_to_the_current_thread = () => result.should_be_equal_to(storage);
+
+ static IDictionary result;
+ static IThread thread;
+ static long thread_id;
+ static Hashtable storage;
+ }
+}
\ No newline at end of file
product/Gorilla.Commons.Infrastructure/Transactions/Thread.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+
+namespace Gorilla.Commons.Infrastructure.Transactions
+{
+ public class Thread : IThread
+ {
+ readonly object mutex = new object();
+ readonly IDictionary<int, LocalDataStoreSlot> slots;
+
+ public Thread()
+ {
+ slots = new Dictionary<int, LocalDataStoreSlot>();
+ }
+
+ public T provide_slot_for<T>() where T : new()
+ {
+ var id = System.Threading.Thread.CurrentThread.ManagedThreadId;
+ within_lock(() =>
+ {
+ if (!slots.ContainsKey(id))
+ {
+ var slot = System.Threading.Thread.GetNamedDataSlot(GetType().FullName);
+ slots.Add(id, slot);
+ System.Threading.Thread.SetData(slot, new T());
+ }
+ });
+ return (T) System.Threading.Thread.GetData(slots[id]);
+ }
+
+ void within_lock(Action action)
+ {
+ lock (mutex) action();
+ }
+ }
+}
\ No newline at end of file
product/Gorilla.Commons.Infrastructure/Gorilla.Commons.Infrastructure.csproj
@@ -130,6 +130,9 @@
<Compile Include="Transactions\ChangeTrackerFactorySpecs.cs" />
<Compile Include="Transactions\ChangeTrackerSpecs.cs" />
<Compile Include="Transactions\Context.cs" />
+ <Compile Include="Transactions\ContextFactory.cs" />
+ <Compile Include="Transactions\ContextFactorySpecs.cs" />
+ <Compile Include="Transactions\Thread.cs" />
<Compile Include="Transactions\EmptyUnitOfWork.cs" />
<Compile Include="Transactions\IChangeTracker.cs" />
<Compile Include="Transactions\IChangeTrackerFactory.cs" />
@@ -140,9 +143,13 @@
<Compile Include="Transactions\IdentityMapSpecs.cs" />
<Compile Include="Transactions\IIdentityMap.cs" />
<Compile Include="Transactions\IKey.cs" />
+ <Compile Include="Transactions\IScopedStorage.cs" />
<Compile Include="Transactions\IStatement.cs" />
<Compile Include="Transactions\IStatementRegistry.cs" />
+ <Compile Include="Transactions\IThread.cs" />
<Compile Include="Transactions\PerThread.cs" />
+ <Compile Include="Transactions\PerThreadScopedStorage.cs" />
+ <Compile Include="Transactions\PerThreadScopedStorageSpecs.cs" />
<Compile Include="Transactions\Session.cs" />
<Compile Include="Transactions\SessionFactory.cs" />
<Compile Include="Transactions\SessionFactorySpecs.cs" />