Commit 05daac5

mo <email@solidware.ca>
2011-04-03 03:34:27
implement handler to lookup stock price.
1 parent b423e28
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">