Commit 05daac5
Changed files (11)
product
desktop.ui
messages
service
specs
unit
service
product/desktop.ui/bootstrappers/Bootstrapper.cs
@@ -3,6 +3,7 @@ using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Autofac;
+using Castle.DynamicProxy;
using gorilla.infrastructure.container;
using gorilla.infrastructure.threading;
using gorilla.utility;
@@ -114,6 +115,7 @@ namespace solidware.financials.windows.ui.bootstrappers
{
builder.RegisterType<PublishEventHandler<AddedNewFamilyMember>>().As<Handles<AddedNewFamilyMember>>();
builder.RegisterType<PublishEventHandler<IncomeMessage>>().As<Handles<IncomeMessage>>();
+ builder.RegisterType<PublishEventHandler<CurrentStockPrice>>().As<Handles<CurrentStockPrice>>();
}
static void server_registration(ContainerBuilder builder)
@@ -134,13 +136,19 @@ namespace solidware.financials.windows.ui.bootstrappers
});
});
- var interceptor = new UnitOfWorkInterceptor(new DB40UnitOfWorkFactory(new DB4OConnectionFactory(), Lazy.load<Context>()));
- builder.RegisterProxy<Handles<FamilyMemberToAdd>, AddNewFamilyMemberHandler>(interceptor);
- builder.RegisterProxy<Handles<FindAllFamily>, FindAllFamilyHandler>(interceptor);
- builder.RegisterProxy<Handles<FindAllIncome>, FindAllIncomeHandler>(interceptor);
- builder.RegisterProxy<Handles<AddIncomeCommandMessage>, AddIncomeCommandMessageHandler>(interceptor);
+ var unit_of_work_interceptor = new UnitOfWorkInterceptor(new DB40UnitOfWorkFactory(new DB4OConnectionFactory(), Lazy.load<Context>()));
+ builder.RegisterProxy<Handles<FamilyMemberToAdd>, AddNewFamilyMemberHandler>(unit_of_work_interceptor);
+ builder.RegisterProxy<Handles<FindAllFamily>, FindAllFamilyHandler>(unit_of_work_interceptor);
+ builder.RegisterProxy<Handles<FindAllIncome>, FindAllIncomeHandler>(unit_of_work_interceptor);
+ builder.RegisterProxy<Handles<AddIncomeCommandMessage>, AddIncomeCommandMessageHandler>(unit_of_work_interceptor);
+
+ var run_in_background = new RunInBackgroundInterceptor(Lazy.load<CommandProcessor>());
+ builder.RegisterProxy<Handles<StockPriceRequestQuery>, StockPriceRequestQueryHandler>(run_in_background);
builder.RegisterType<ConfigureServiceMappings>().As<NeedStartup>();
+
+ builder.RegisterType<StubLookupService>().As<StockPriceLookupService>();
+
new DB4OBootstrapper().run();
}
}
product/desktop.ui/RunInBackgroundInterceptor.cs
@@ -0,0 +1,23 @@
+using Castle.DynamicProxy;
+using gorilla.infrastructure.threading;
+
+namespace solidware.financials.windows.ui
+{
+ public class RunInBackgroundInterceptor : IInterceptor
+ {
+ CommandProcessor command_processor;
+
+ public RunInBackgroundInterceptor(CommandProcessor command_processor)
+ {
+ this.command_processor = command_processor;
+ }
+
+ public void Intercept(IInvocation invocation)
+ {
+ command_processor.add(() =>
+ {
+ invocation.Proceed();
+ });
+ }
+ }
+}
\ No newline at end of file
product/desktop.ui/solidware.financials.csproj
@@ -114,6 +114,7 @@
<Compile Include="bootstrappers\ComposeShell.cs" />
<Compile Include="bootstrappers\ConfigureMappings.cs" />
<Compile Include="bootstrappers\DefaultMapper.cs" />
+ <Compile Include="RunInBackgroundInterceptor.cs" />
<Compile Include="bootstrappers\StopEssentialServices.cs" />
<Compile Include="bootstrappers\WireUpSubscribers.cs" />
<Compile Include="CancelCommand.cs" />
product/messages/CurrentStockPrice.cs
@@ -0,0 +1,11 @@
+using gorilla.utility;
+using solidware.financials.infrastructure.eventing;
+
+namespace solidware.financials.messages
+{
+ public class CurrentStockPrice : ValueType<CurrentStockPrice>, Event
+ {
+ public string Symbol { get; set; }
+ public decimal Price { get; set; }
+ }
+}
\ No newline at end of file
product/messages/messages.csproj
@@ -46,6 +46,7 @@
<ItemGroup>
<Compile Include="AddedNewFamilyMember.cs" />
<Compile Include="AddIncomeCommandMessage.cs" />
+ <Compile Include="CurrentStockPrice.cs" />
<Compile Include="FamilyMemberToAdd.cs" />
<Compile Include="FindAllFamily.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
product/service/handlers/StockPriceLookupService.cs
@@ -0,0 +1,15 @@
+namespace solidware.financials.service.handlers
+{
+ public interface StockPriceLookupService
+ {
+ decimal FindPriceFor(string symbol);
+ }
+
+ public class StubLookupService : StockPriceLookupService
+ {
+ public decimal FindPriceFor(string symbol)
+ {
+ return 24.00m;
+ }
+ }
+}
\ No newline at end of file
product/service/handlers/StockPriceRequestQueryHandler.cs
@@ -0,0 +1,26 @@
+using solidware.financials.infrastructure;
+using solidware.financials.messages;
+
+namespace solidware.financials.service.handlers
+{
+ public class StockPriceRequestQueryHandler : Handles<StockPriceRequestQuery>
+ {
+ ServiceBus bus;
+ StockPriceLookupService service;
+
+ public StockPriceRequestQueryHandler(ServiceBus bus, StockPriceLookupService service)
+ {
+ this.bus = bus;
+ this.service = service;
+ }
+
+ public void handle(StockPriceRequestQuery item)
+ {
+ bus.publish(new CurrentStockPrice
+ {
+ Symbol = item.Symbol,
+ Price = service.FindPriceFor(item.Symbol),
+ });
+ }
+ }
+}
\ No newline at end of file
product/service/service.csproj
@@ -114,6 +114,8 @@
<Compile Include="domain\Person.cs" />
<Compile Include="handlers\FindAllFamilyHandler.cs" />
<Compile Include="handlers\FindAllIncomeHandler.cs" />
+ <Compile Include="handlers\StockPriceLookupService.cs" />
+ <Compile Include="handlers\StockPriceRequestQueryHandler.cs" />
<Compile Include="orm\Connection.cs" />
<Compile Include="orm\ConnectionFactory.cs" />
<Compile Include="orm\DB4OConnection.cs" />
product/specs/unit/service/handlers/StockPriceRequestQueryHandlerSpecs.cs
@@ -0,0 +1,49 @@
+using Machine.Specifications;
+using solidware.financials.infrastructure;
+using solidware.financials.messages;
+using solidware.financials.service.handlers;
+
+namespace specs.unit.service.handlers
+{
+ public class StockPriceRequestQueryHandlerSpecs
+ {
+ public abstract class concern
+ {
+ Establish context = () =>
+ {
+ bus = Create.dependency<ServiceBus>();
+ service = Create.dependency<StockPriceLookupService>();
+ sut = new StockPriceRequestQueryHandler(bus, service);
+ };
+
+ static protected StockPriceRequestQueryHandler sut;
+ static protected ServiceBus bus;
+ static protected StockPriceLookupService service;
+ }
+
+ public class when_looking_up_the_current_price_of_a_known_symbol : concern
+ {
+ Establish context = () =>
+ {
+ query = new StockPriceRequestQuery {Symbol = "ARX.TO"};
+ service.is_told_to(x => x.FindPriceFor("ARX.TO")).it_will_return(26.81m);
+ };
+
+ Because of = () =>
+ {
+ sut.handle(query);
+ };
+
+ It should_publish_the_current_price = () =>
+ {
+ bus.was_told_to(x => x.publish(new CurrentStockPrice
+ {
+ Symbol = "ARX.TO",
+ Price = 26.81m,
+ }));
+ };
+
+ static StockPriceRequestQuery query;
+ }
+ }
+}
\ No newline at end of file
product/specs/unit/ui/RunInBackgroundInterceptorSpecs.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Castle.DynamicProxy;
+using gorilla.infrastructure.threading;
+using gorilla.utility;
+using Machine.Specifications;
+using solidware.financials.windows.ui;
+
+namespace specs.unit.ui
+{
+ public class RunInBackgroundInterceptorSpecs
+ {
+ public abstract class concern
+ {
+ Establish context = () =>
+ {
+ processor = new TestCommandProcessor();
+ sut = new RunInBackgroundInterceptor(processor);
+ };
+
+ static protected RunInBackgroundInterceptor sut;
+ static protected TestCommandProcessor processor;
+ }
+
+ public class when_running_all_actions_against_a_proxy_on_a_background_thread : concern
+ {
+ Establish context = () =>
+ {
+ invocation = Create.an<IInvocation>();
+ };
+
+ Because of = () =>
+ {
+ sut.Intercept(invocation);
+ };
+
+ It should_push_a_command_on_the_background_thread_to_invoke_the_call = () =>
+ {
+ invocation.was_not_told_to(x => x.Proceed());
+ processor.actions.Count.should_be_equal_to(1);
+ processor.actions.First().Invoke();
+ invocation.received(x => x.Proceed());
+ };
+
+ static IInvocation invocation;
+ }
+ }
+
+ public class TestCommandProcessor : CommandProcessor
+ {
+ public List<Action> actions = new List<Action>();
+
+ public void run() {}
+
+ public void add(Action command)
+ {
+ actions.add(command);
+ }
+
+ public void add(Command command_to_process)
+ {
+ add(command_to_process.run);
+ }
+
+ public void stop() {}
+ }
+}
\ No newline at end of file
product/specs/specs.csproj
@@ -98,6 +98,7 @@
<Compile Include="unit\service\domain\payroll\MoneySpecs.cs" />
<Compile Include="unit\service\domain\property_bag\PropertyBagSpecs.cs" />
<Compile Include="unit\service\handlers\AddIncomeCommandMessageHandlerSpecs.cs" />
+ <Compile Include="unit\service\handlers\StockPriceRequestQueryHandlerSpecs.cs" />
<Compile Include="unit\service\orm\DB4OUnitOfWorkFactorySpecs.cs" />
<Compile Include="unit\service\orm\DB4OUnitOfWorkSpecs.cs" />
<Compile Include="unit\service\orm\EmptyUnitOfWorkSpecs.cs" />
@@ -109,6 +110,7 @@
<Compile Include="unit\ui\presenters\AddNewStockSymbolPresenterSpecs.cs" />
<Compile Include="unit\ui\presenters\specifications\IfFamilyMemberIsSelectedSpecs.cs" />
<Compile Include="unit\ui\presenters\StockWatchPresenterSpecs.cs" />
+ <Compile Include="unit\ui\RunInBackgroundInterceptorSpecs.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\desktop.ui\solidware.financials.csproj">