Commit 9451070
Changed files (16)
product
desktop.ui
bootstrappers
infrastructure
service
specs
unit
service
product/desktop.ui/bootstrappers/Bootstrapper.cs
@@ -100,13 +100,25 @@ namespace solidware.financials.windows.ui.bootstrappers
static void server_registration(ContainerBuilder builder)
{
- var interceptor = new UnitOfWorkInterceptor(null);
- builder.RegisterProxy<Handles<FamilyMemberToAdd>, AddNewFamilyMemberHandler>(interceptor);
- builder.RegisterProxy<Handles<FindAllFamily>, FindAllFamilyHandler>(interceptor);
- builder.RegisterType<InMemoryDatabase>().As<PersonRepository>().SingleInstance();
+ //builder.RegisterType<InMemoryDatabase>().As<PersonRepository>().SingleInstance();
+ builder.RegisterType<DB4OPersonRepository>().As<PersonRepository>().SingleInstance();
builder.RegisterType<ScopedContext>().As<Context>().SingleInstance();
+ //builder.Register(x => new SimpleContext(new Hashtable())).As<Context>().SingleInstance();
builder.RegisterType<PerThreadScopedStorage>().As<IScopedStorage>();
builder.RegisterType<CurrentThread>().As<IThread>();
+ builder.Register(x =>
+ {
+ return Lazy.load(() =>
+ {
+ var context = Resolve.the<Context>();
+ var key = new TypedKey<Connection>();
+ return context.value_for(key);
+ });
+ });
+
+ var interceptor = new UnitOfWorkInterceptor(new DB40UnitOfWorkFactory(new DB4OConnectionFactory(), Lazy.load<Context>()) );
+ builder.RegisterProxy<Handles<FamilyMemberToAdd>, AddNewFamilyMemberHandler>(interceptor);
+ builder.RegisterProxy<Handles<FindAllFamily>, FindAllFamilyHandler>(interceptor);
new DB4OBootstrapper().run();
}
}
product/desktop.ui/solidware.financials.csproj
@@ -61,6 +61,7 @@
<HintPath>..\..\thirdparty\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="Castle.Core, Version=2.5.1.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL" />
+ <Reference Include="Db4objects.Db4o, Version=8.0.184.15484, Culture=neutral, PublicKeyToken=6199cd4f203aa8eb, processorArchitecture=MSIL" />
<Reference Include="gorilla.infrastructure">
<HintPath>..\..\thirdparty\commons\gorilla.infrastructure.dll</HintPath>
</Reference>
product/infrastructure/CastleProxyFactory.cs
@@ -1,4 +1,7 @@
-using Castle.DynamicProxy;
+using System;
+using Castle.DynamicProxy;
+using gorilla.infrastructure.container;
+using gorilla.utility;
namespace solidware.financials.infrastructure
{
@@ -6,9 +9,56 @@ namespace solidware.financials.infrastructure
{
ProxyGenerator generator = new ProxyGenerator();
- public Interface CreateProxyFor<Interface>(Interface target, params IInterceptor[] interceptors) where Interface : class
+ public Interface CreateProxyFor<Interface>(Interface target, params IInterceptor[] interceptors)
+ where Interface : class
{
return generator.CreateInterfaceProxyWithTarget(target, interceptors);
}
}
+
+ static public class Lazy
+ {
+ static public T load<T>() where T : class
+ {
+ return load(Resolve.the<T>);
+ }
+
+ static public T load<T>(Func<T> get_the_implementation) where T : class
+ {
+ return create_proxy_for<T>(create_interceptor_for(get_the_implementation));
+ }
+
+ static IInterceptor create_interceptor_for<T>(Func<T> get_the_implementation) where T : class
+ {
+ return new LazyLoadedInterceptor<T>(get_the_implementation.memorize());
+ }
+
+ static T create_proxy_for<T>(IInterceptor interceptor) where T : class
+ {
+ return new ProxyGenerator().CreateInterfaceProxyWithoutTarget<T>(interceptor);
+ }
+
+ class LazyLoadedInterceptor<T> : IInterceptor
+ {
+ readonly Func<T> get_the_implementation;
+
+ public LazyLoadedInterceptor(Func<T> get_the_implementation)
+ {
+ this.get_the_implementation = get_the_implementation;
+ }
+
+ public void Intercept(IInvocation invocation)
+ {
+ var method = invocation.GetConcreteMethodInvocationTarget();
+ if( null== method)
+ {
+ invocation.ReturnValue = invocation.Method.Invoke(get_the_implementation(), invocation.Arguments);
+ }
+ else
+ {
+ invocation.ReturnValue = method.Invoke(get_the_implementation(), invocation.Arguments);
+ }
+ }
+ }
+ }
}
\ No newline at end of file
product/service/orm/ConnectionFactory.cs
@@ -4,4 +4,4 @@
{
Connection Open();
}
-}
\ No newline at end of file
+}
product/service/orm/DB40UnitOfWork.cs
@@ -1,21 +0,0 @@
-using System;
-
-namespace solidware.financials.service.orm
-{
- public class DB40UnitOfWork : UnitOfWork
- {
- public DB40UnitOfWork(Connection connection)
- {
- }
-
- public void Dispose()
- {
- throw new NotImplementedException();
- }
-
- public void commit()
- {
- throw new NotImplementedException();
- }
- }
-}
\ No newline at end of file
product/service/orm/DB40UnitOfWorkFactory.cs
@@ -20,7 +20,7 @@ namespace solidware.financials.service.orm
var connection = factory.Open();
context.add(key, connection);
- return new DB4OUnitOfWork(connection);
+ return new DB4OUnitOfWork(connection, context);
}
}
}
\ No newline at end of file
product/service/orm/DB4OConnection.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Db4objects.Db4o;
+using Db4objects.Db4o.Ext;
+using Db4objects.Db4o.Query;
+
+namespace solidware.financials.service.orm
+{
+ public class DB4OConnection : Connection
+ {
+ readonly IEmbeddedObjectContainer session;
+
+ public DB4OConnection(IEmbeddedObjectContainer session)
+ {
+ this.session = session;
+ }
+
+ public void Dispose()
+ {
+ session.Dispose();
+ }
+
+ public void Activate(object obj, int depth)
+ {
+ session.Activate(obj, depth);
+ }
+
+ public bool Close()
+ {
+ return session.Close();
+ }
+
+ public void Commit()
+ {
+ session.Commit();
+ }
+
+ public void Deactivate(object obj, int depth)
+ {
+ session.Deactivate(obj, depth);
+ }
+
+ public void Delete(object obj)
+ {
+ session.Delete(obj);
+ }
+
+ public IExtObjectContainer Ext()
+ {
+ return session.Ext();
+ }
+
+ public IObjectSet QueryByExample(object template)
+ {
+ return session.QueryByExample(template);
+ }
+
+ public IQuery Query()
+ {
+ return session.Query();
+ }
+
+ public IObjectSet Query(Type clazz)
+ {
+ return session.Query(clazz);
+ }
+
+ public IObjectSet Query(Predicate predicate)
+ {
+ return session.Query(predicate);
+ }
+
+ public IObjectSet Query(Predicate predicate, IQueryComparator comparator)
+ {
+ return session.Query(predicate, comparator);
+ }
+
+ public IObjectSet Query(Predicate predicate, IComparer comparer)
+ {
+ return session.Query(predicate, comparer);
+ }
+
+ public void Rollback()
+ {
+ session.Rollback();
+ }
+
+ public void Store(object obj)
+ {
+ session.Store(obj);
+ }
+
+ public IList<Extent> Query<Extent>(Predicate<Extent> match)
+ {
+ return session.Query(match);
+ }
+
+ public IList<Extent> Query<Extent>(Predicate<Extent> match, IComparer<Extent> comparer)
+ {
+ return session.Query(match, comparer);
+ }
+
+ public IList<Extent> Query<Extent>(Predicate<Extent> match, Comparison<Extent> comparison)
+ {
+ return session.Query(match, comparison);
+ }
+
+ public IList<ElementType> Query<ElementType>(Type extent)
+ {
+ return session.Query<ElementType>(extent);
+ }
+
+ public IList<Extent> Query<Extent>()
+ {
+ return session.Query<Extent>();
+ }
+
+ public IList<Extent> Query<Extent>(IComparer<Extent> comparer)
+ {
+ return session.Query(comparer);
+ }
+
+ public void Backup(string path)
+ {
+ session.Backup(path);
+ }
+ }
+}
\ No newline at end of file
product/service/orm/DB4OConnectionFactory.cs
@@ -0,0 +1,39 @@
+using System;
+using System.IO;
+using Db4objects.Db4o;
+
+namespace solidware.financials.service.orm
+{
+ public class DB4OConnectionFactory : ConnectionFactory
+ {
+ public DB4OConnectionFactory()
+ {
+ database_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"mokhan.ca\momoney\default.db4o");
+ }
+
+ public Connection Open()
+ {
+ if (null == connection)
+ {
+ ensure_directories_exist();
+ connection = new DB4OConnection(Db4oEmbedded.OpenFile(database_path));
+ }
+ return connection;
+ }
+
+ void ensure_directories_exist()
+ {
+ var company_dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
+ @"mokhan.ca");
+ if (!Directory.Exists(company_dir))
+ Directory.CreateDirectory(company_dir);
+
+ var application_dir = Path.Combine(company_dir, "momoney");
+ if (!Directory.Exists(application_dir))
+ Directory.CreateDirectory(application_dir);
+ }
+
+ string database_path;
+ DB4OConnection connection;
+ }
+}
\ No newline at end of file
product/service/orm/DB4OPersonRepository.cs
@@ -1,16 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Db4objects.Db4o;
using solidware.financials.service.domain;
namespace solidware.financials.service.orm
{
public class DB4OPersonRepository : PersonRepository
{
- IObjectContainer session;
+ Connection session;
- public DB4OPersonRepository(IObjectContainer session)
+ public DB4OPersonRepository(Connection session)
{
this.session = session;
}
product/service/orm/DB4OUnitOfWork.cs
@@ -1,19 +1,17 @@
-namespace solidware.financials.service.orm
+using gorilla.utility;
+
+namespace solidware.financials.service.orm
{
public class DB4OUnitOfWork : UnitOfWork
{
readonly Connection connection;
+ readonly Context context;
bool was_committed;
- public DB4OUnitOfWork(Connection connection)
+ public DB4OUnitOfWork(Connection connection, Context context)
{
this.connection = connection;
- }
-
- public void Dispose()
- {
- if (!was_committed) connection.Rollback();
- connection.Dispose();
+ this.context = context;
}
public void commit()
@@ -21,5 +19,12 @@
connection.Commit();
was_committed = true;
}
+
+ public void Dispose()
+ {
+ if (!was_committed) connection.Rollback();
+ //connection.Dispose();
+ context.remove(new TypedKey<Connection>());
+ }
}
}
\ No newline at end of file
product/service/orm/EmptyUnitOfWork.cs
@@ -1,17 +1,13 @@
-using System;
-
-namespace solidware.financials.service.orm
+namespace solidware.financials.service.orm
{
public class EmptyUnitOfWork : UnitOfWork
{
public void Dispose()
{
- throw new NotImplementedException();
}
public void commit()
{
- throw new NotImplementedException();
}
}
}
\ No newline at end of file
product/service/DB4OBootstrapper.cs
@@ -1,7 +1,6 @@
using System;
using System.Configuration;
using System.IO;
-using Db4objects.Db4o;
using gorilla.utility;
using solidware.financials.service.orm;
@@ -9,8 +8,7 @@ namespace solidware.financials.service
{
public class DB4OBootstrapper : Command
{
- string database_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
- @"mokhan.ca\momoney\default.db4o");
+ string database_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"mokhan.ca\momoney\default.db4o");
Settings settings = new Settings(ConfigurationManager.AppSettings);
@@ -19,23 +17,10 @@ namespace solidware.financials.service
if (settings.named<bool>("reset.db"))
if (File.Exists(database_path)) File.Delete(database_path);
- ensure_directories_exist();
-
- using (var database = Db4oEmbedded.OpenFile(database_path))
+ using (var database = new DB4OConnectionFactory().Open())
{
database.Store(new LastOpened(Clock.now()));
}
}
-
- void ensure_directories_exist()
- {
- var company_dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"mokhan.ca");
- if (!Directory.Exists(company_dir))
- Directory.CreateDirectory(company_dir);
-
- var application_dir = Path.Combine(company_dir, "momoney");
- if (!Directory.Exists(application_dir))
- Directory.CreateDirectory(application_dir);
- }
}
}
\ No newline at end of file
product/service/service.csproj
@@ -59,6 +59,8 @@
<Compile Include="handlers\FindAllFamilyHandler.cs" />
<Compile Include="orm\Connection.cs" />
<Compile Include="orm\ConnectionFactory.cs" />
+ <Compile Include="orm\DB4OConnection.cs" />
+ <Compile Include="orm\DB4OConnectionFactory.cs" />
<Compile Include="orm\DB4OUnitOfWork.cs" />
<Compile Include="orm\DB40UnitOfWorkFactory.cs" />
<Compile Include="orm\DB4OPersonRepository.cs" />
product/specs/unit/service/orm/DB4OUnitOfWorkSpecs.cs
@@ -1,3 +1,4 @@
+using gorilla.utility;
using Machine.Specifications;
using Rhino.Mocks;
using solidware.financials.service.orm;
@@ -11,11 +12,13 @@ namespace specs.unit.service.orm
Establish context = () =>
{
session = Create.dependency<Connection>();
- sut = new DB4OUnitOfWork(session);
+ the_context = Create.dependency<Context>();
+ sut = new DB4OUnitOfWork(session, the_context);
};
static protected DB4OUnitOfWork sut;
static protected Connection session;
+ static Context the_context;
}
[Subject(typeof(DB4OUnitOfWork))]
product/specs/unit/service/orm/EmptyUnitOfWorkSpecs.cs
@@ -0,0 +1,25 @@
+using Machine.Specifications;
+using solidware.financials.service.orm;
+
+namespace specs.unit.service.orm
+{
+ public class EmptyUnitOfWorkSpecs
+ {
+ [Subject(typeof(EmptyUnitOfWork))]
+ public class When_disposing_an_empty_unit_of_work
+ {
+ It should_not_do_anything = () =>
+ {
+ new EmptyUnitOfWork().Dispose();
+ };
+ }
+ [Subject(typeof(EmptyUnitOfWork))]
+ public class When_committing_an_empty_unit_of_work
+ {
+ It should_not_do_anything = () =>
+ {
+ new EmptyUnitOfWork().commit();
+ };
+ }
+ }
+}
\ No newline at end of file
product/specs/specs.csproj
@@ -65,6 +65,7 @@
<Compile Include="unit\infrastructure\ProxyFactorySpecs.cs" />
<Compile Include="unit\service\orm\DB4OUnitOfWorkFactorySpecs.cs" />
<Compile Include="unit\service\orm\DB4OUnitOfWorkSpecs.cs" />
+ <Compile Include="unit\service\orm\EmptyUnitOfWorkSpecs.cs" />
<Compile Include="unit\service\orm\UnitOfWorkInterceptorSpecs.cs" />
<Compile Include="unit\ui\InMemoryApplicationStateSpecs.cs" />
<Compile Include="unit\ui\presenters\AddFamilyMemberPresenterSpecs.cs" />