Commit 45cdce2
Changed files (6)
product
application.console
application.console
infrastructure
application.tests
console
infrastructure
product/application.console/application.console/infrastructure/Factory.cs
@@ -4,7 +4,7 @@ namespace gorilla.migrations.console.infrastructure
{
public class Factory : Scope
{
- public object apply_to(Func<object> factory)
+ public T apply_to<T>(Func<T> factory)
{
return factory();
}
product/application.console/application.console/infrastructure/Scope.cs
@@ -4,6 +4,6 @@ namespace gorilla.migrations.console.infrastructure
{
public interface Scope
{
- object apply_to(Func<object> factory);
+ T apply_to<T>(Func<T> factory);
}
}
\ No newline at end of file
product/application.console/application.console/infrastructure/Singleton.cs
@@ -0,0 +1,46 @@
+using System;
+
+namespace gorilla.migrations.console.infrastructure
+{
+ public class Singleton : Scope
+ {
+ Func<object> cached_factory;
+
+ public T apply_to<T>(Func<T> factory)
+ {
+ if (null == cached_factory)
+ {
+ cached_factory = factory.memoize().as_anonymous();
+ }
+ return (T) cached_factory();
+ }
+ }
+
+ static public class FuncExtensions
+ {
+ static readonly object mutex = new object();
+
+ static public Func<T> memoize<T>(this Func<T> factory)
+ {
+ var item = default(T);
+
+ return () =>
+ {
+ if (null == item)
+ {
+ lock (mutex)
+ {
+ if (null == item)
+ item = factory();
+ }
+ }
+ return item;
+ };
+ }
+
+ static public Func<object> as_anonymous<T>(this Func<T> factory)
+ {
+ return () => factory();
+ }
+ }
+}
\ No newline at end of file
product/application.console/application.console/application.console.csproj
@@ -53,6 +53,7 @@
<Compile Include="infrastructure\Scope.cs" />
<Compile Include="infrastructure\SimpleContainer.cs" />
<Compile Include="infrastructure\SimpleContainerBuilder.cs" />
+ <Compile Include="infrastructure\Singleton.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
product/application.tests/console/infrastructure/SingletonSpecs.cs
@@ -0,0 +1,30 @@
+using System;
+using developwithpassion.bdd.contexts;
+using developwithpassion.bdd.harnesses.mbunit;
+using developwithpassion.bdddoc.core;
+using gorilla.migrations.console.infrastructure;
+
+namespace tests.console.infrastructure
+{
+ public class SingletonSpecs
+ {
+ public abstract class concern : observations_for_a_sut_with_a_contract<Scope, Singleton> {}
+
+ [Concern(typeof (Singleton))]
+ public class when_retrieving_a_singleton_instance : concern
+ {
+ it should_return_the_same_instance_each_time = () =>
+ {
+ Func<TimeStamp> factory = () => new TimeStamp {time = DateTime.Now};
+ var first = controller.sut.apply_to(factory);
+ var second = controller.sut.apply_to(factory);
+ ReferenceEquals(first, second).should_be_true();
+ };
+ }
+
+ public class TimeStamp
+ {
+ public DateTime time { get; set; }
+ }
+ }
+}
\ No newline at end of file
product/application.tests/application.tests.csproj
@@ -70,6 +70,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="console\infrastructure\FactorySpecs.cs" />
+ <Compile Include="console\infrastructure\SingletonSpecs.cs" />
<Compile Include="console\SimpleContainerSpecs.cs" />
<Compile Include="core\CommandRegistrySpecs.cs" />
<Compile Include="core\ConsoleArgumentsSpecs.cs" />