Commit dee35bf

unknown <mo@.(none)>
2010-01-27 04:57:57
attempting to register views as singletons.
1 parent b04747e
Changed files (99)
product
client
boot
presentation
Core
Model
Presenters
Views
Winforms
service
service.infrastructure
commons
product/client/boot/boot/container/registration/proxy_configuration/NotifyProgressInterceptor.cs
@@ -10,9 +10,9 @@ namespace MoMoney.boot.container.registration.proxy_configuration
 
     public class NotifyProgressInterceptor : INotifyProgressInterceptor
     {
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
 
-        public NotifyProgressInterceptor(IEventAggregator broker)
+        public NotifyProgressInterceptor(EventAggregator broker)
         {
             this.broker = broker;
         }
product/client/boot/boot/container/registration/proxy_configuration/UnitOfWorkInterceptor.cs
@@ -9,10 +9,10 @@ namespace MoMoney.boot.container.registration.proxy_configuration
 
     public class UnitOfWorkInterceptor : IUnitOfWorkInterceptor
     {
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
         readonly IUnitOfWorkFactory factory;
 
-        public UnitOfWorkInterceptor(IEventAggregator broker, IUnitOfWorkFactory factory)
+        public UnitOfWorkInterceptor(EventAggregator broker, IUnitOfWorkFactory factory)
         {
             this.broker = broker;
             this.factory = factory;
product/client/boot/boot/container/registration/IContainerStartup.cs
@@ -0,0 +1,7 @@
+using gorilla.commons.infrastructure.thirdparty;
+using gorilla.commons.utility;
+
+namespace MoMoney.boot.container.registration
+{
+    public interface IContainerStartup : ParameterizedCommand<DependencyRegistration> { }
+}
\ No newline at end of file
product/client/boot/boot/container/registration/wire_up_the_infrastructure_in_to_the.cs
@@ -25,7 +25,7 @@ namespace MoMoney.boot.container.registration
 
         public void run()
         {
-            registry.singleton<IEventAggregator, EventAggregator>();
+            registry.singleton<EventAggregator, SynchronizedEventAggregator>();
             registry.singleton<ITimer, IntervalTimer>();
             registry.singleton<IProjectController, ProjectController>();
             registry.transient(typeof (Registry<>), typeof (DefaultRegistry<>));
@@ -46,7 +46,7 @@ namespace MoMoney.boot.container.registration
                     : (IDeployment) new NullDeployment());
 
             registry.transient<ICommandPump, CommandPump>();
-            registry.transient<ICommandFactory, CommandFactory>();
+            registry.transient<CommandFactory, SynchronizedCommandFactory>();
             registry.transient<ISynchronizationContextFactory, SynchronizationContextFactory>();
             registry.singleton<CommandProcessor, AsynchronousCommandProcessor>();
         }
product/client/boot/boot/container/registration/wire_up_the_presentation_modules.cs
@@ -32,7 +32,7 @@ namespace MoMoney.boot.container.registration
         public void run(Assembly item)
         {
             Func<IApplicationController> target =
-                () => new ApplicationController(Lazy.load<IShell>(), Lazy.load<PresenterFactory>(), Lazy.load<IEventAggregator>());
+                () => new ApplicationController(Lazy.load<Shell>(), Lazy.load<PresenterFactory>(), Lazy.load<EventAggregator>());
             registry.proxy<IApplicationController, SynchronizedConfiguration<IApplicationController>>(target.memorize());
             registry.transient(typeof (IRunThe<>), typeof (RunThe<>));
             registry.transient<IFileMenu, FileMenu>();
@@ -42,11 +42,11 @@ namespace MoMoney.boot.container.registration
 
             item
                 .all_types()
-                .where(x => typeof (IPresenter).IsAssignableFrom(x))
+                .where(x => typeof (Presenter).IsAssignableFrom(x))
                 .where(x => !x.IsInterface)
                 .where(x => !x.IsAbstract)
                 .where(x => !x.IsGenericType)
-                .each(type => registry.transient(typeof (IPresenter), type));
+                .each(type => registry.transient(typeof (Presenter), type));
 
             item
                 .all_types()
product/client/boot/boot/container/registration/wire_up_the_reports_in_to_the.cs
@@ -21,11 +21,11 @@ namespace MoMoney.boot.container.registration
 
         public void run()
         {
-            registry.transient<IReportViewer, ReportViewer>();
-            registry.transient(typeof (IPresenter), typeof (ReportPresenter<IViewAllBillsReport, IEnumerable<BillInformationDTO>, IGetAllBillsQuery>));
-            registry.transient<IViewAllBillsReport, ViewAllBillsReport>();
-            registry.transient(typeof (IPresenter), typeof (ReportPresenter<IViewAllIncomeReport, IEnumerable<IncomeInformationDTO>, IGetAllIncomeQuery>));
-            registry.transient<IViewAllIncomeReport, ViewAllIncomeReport>();
+            registry.singleton<IReportViewer, ReportViewer>();
+            registry.transient(typeof (Presenter), typeof (ReportPresenter<IViewAllBillsReport, IEnumerable<BillInformationDTO>, IGetAllBillsQuery>));
+            registry.singleton<IViewAllBillsReport, ViewAllBillsReport>();
+            registry.transient(typeof (Presenter), typeof (ReportPresenter<IViewAllIncomeReport, IEnumerable<IncomeInformationDTO>, IGetAllIncomeQuery>));
+            registry.singleton<IViewAllIncomeReport, ViewAllIncomeReport>();
         }
     }
 }
\ No newline at end of file
product/client/boot/boot/container/registration/wire_up_the_views_in_to_the.cs
@@ -20,27 +20,27 @@ namespace MoMoney.boot.container.registration
         public void run()
         {
             var shell = new ApplicationShell();
-            register.singleton<IShell>(() => shell);
+            register.singleton<Shell>(() => shell);
             register.singleton<IWin32Window>(() => shell);
             register.singleton<ISynchronizeInvoke>(() => shell);
             register.singleton<IRegionManager>(() => shell);
             register.singleton(() => shell);
-            register.transient<IAboutApplicationView, AboutTheApplicationView>();
-            register.transient<ISplashScreenView, SplashScreenView>();
-            register.transient<INavigationView, NavigationView>();
-            register.transient<IAddCompanyView, AddCompanyView>();
-            register.transient<IViewAllBills, ViewAllBills>();
-            register.transient<IAddBillPaymentView, AddBillPaymentView>();
-            register.transient<IMainMenuView, MainMenuView>();
-            register.transient<IAddNewIncomeView, AddNewIncomeView>();
-            register.transient<IViewIncomeHistory, ViewAllIncome>();
+            register.singleton<IAboutApplicationView, AboutTheApplicationView>();
+            register.singleton<ISplashScreenView, SplashScreenView>();
+            register.singleton<INavigationView, NavigationView>();
+            register.singleton<IAddCompanyView, AddCompanyView>();
+            register.singleton<IViewAllBills, ViewAllBills>();
+            register.singleton<IAddBillPaymentView, AddBillPaymentView>();
+            register.singleton<IMainMenuView, MainMenuView>();
+            register.singleton<IAddNewIncomeView, AddNewIncomeView>();
+            register.singleton<IViewIncomeHistory, ViewAllIncome>();
             register.transient<ISaveChangesView, SaveChangesView>();
             register.transient<ICheckForUpdatesView, CheckForUpdatesView>();
             register.singleton<INotificationIconView, NotificationIconView>();
-            register.transient<IStatusBarView, StatusBarView>();
+            register.singleton<IStatusBarView, StatusBarView>();
             register.transient<IUnhandledErrorView, UnhandledErrorView>();
-            register.transient<IGettingStartedView, WelcomeScreen>();
-            register.transient<ILogFileView, LogFileView>();
+            register.singleton<IGettingStartedView, WelcomeScreen>();
+            register.singleton<ILogFileView, LogFileView>();
         }
     }
 }
\ No newline at end of file
product/client/boot/boot/container/ComponentExclusionSpecification.cs
@@ -19,7 +19,7 @@ namespace MoMoney.boot.container
                 .or(type.is_a<Entity>())
                 .or(type.is_an_interface())
                 .or(type.is_abstract())
-                .or(type.is_a<IPresenter>())
+                .or(type.is_a<Presenter>())
                 .or(type.is_a<IModule>())
                 .is_satisfied_by(type);
         }
product/client/boot/boot/global_error_handling.cs
@@ -19,7 +19,7 @@ namespace MoMoney.boot
         void handle(Exception e)
         {
             e.add_to_log();
-            Resolve.the<IEventAggregator>().publish(new UnhandledErrorOccurred(e));
+            Resolve.the<EventAggregator>().publish(new UnhandledErrorOccurred(e));
         }
     }
 }
\ No newline at end of file
product/client/boot/boot/WindowsFormsApplication.cs
@@ -56,7 +56,7 @@ namespace MoMoney.boot
             catch (Exception e)
             {
                 this.log().error(e);
-                Resolve.the<IEventAggregator>().publish(new UnhandledErrorOccurred(e));
+                Resolve.the<EventAggregator>().publish(new UnhandledErrorOccurred(e));
             }
         }
     }
product/client/boot/Modules/Core/LoadPresentationModulesCommand.cs
@@ -7,9 +7,9 @@ namespace MoMoney.Modules.Core
     public class LoadPresentationModulesCommand : ILoadPresentationModulesCommand
     {
         Registry<IModule> registry;
-        IEventAggregator broker;
+        EventAggregator broker;
 
-        public LoadPresentationModulesCommand(Registry<IModule> registry, IEventAggregator broker)
+        public LoadPresentationModulesCommand(Registry<IModule> registry, EventAggregator broker)
         {
             this.registry = registry;
             this.broker = broker;
product/client/boot/Modules/ApplicationMenuModule.cs
@@ -9,15 +9,15 @@ namespace MoMoney.Modules
 {
     public class ApplicationMenuModule :
         IModule,
-        IEventSubscriber<NewProjectOpened>,
-        IEventSubscriber<ClosingProjectEvent>,
-        IEventSubscriber<SavedChangesEvent>,
-        IEventSubscriber<UnsavedChangesEvent>
+        EventSubscriber<NewProjectOpened>,
+        EventSubscriber<ClosingProjectEvent>,
+        EventSubscriber<SavedChangesEvent>,
+        EventSubscriber<UnsavedChangesEvent>
     {
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
         readonly IRunPresenterCommand command;
 
-        public ApplicationMenuModule(IEventAggregator broker, IRunPresenterCommand command)
+        public ApplicationMenuModule(EventAggregator broker, IRunPresenterCommand command)
         {
             this.broker = broker;
             this.command = command;
product/client/boot/Modules/DatabaseModule.cs
@@ -6,9 +6,9 @@ namespace MoMoney.Modules
     public class DatabaseModule : IDatabaseModule
     {
         readonly IDatabaseConfiguration configuration;
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
 
-        public DatabaseModule(IDatabaseConfiguration configuration, IEventAggregator broker)
+        public DatabaseModule(IDatabaseConfiguration configuration, EventAggregator broker)
         {
             this.configuration = configuration;
             this.broker = broker;
product/client/boot/Modules/GettingStartedModule.cs
@@ -8,8 +8,8 @@ namespace MoMoney.Modules
 {
     public class GettingStartedModule :
         IModule,
-        IEventSubscriber<NewProjectOpened>,
-        IEventSubscriber<ClosingProjectEvent>
+        EventSubscriber<NewProjectOpened>,
+        EventSubscriber<ClosingProjectEvent>
     {
         IRunPresenterCommand command;
 
product/client/boot/Modules/MainMenuModule.cs
@@ -5,7 +5,7 @@ using MoMoney.Service.Infrastructure.Eventing;
 
 namespace MoMoney.Modules
 {
-    public class MainMenuModule : IModule, IEventSubscriber<NewProjectOpened>
+    public class MainMenuModule : IModule, EventSubscriber<NewProjectOpened>
     {
         readonly IRunPresenterCommand command;
 
product/client/boot/Modules/NavigationModule.cs
@@ -6,7 +6,7 @@ using MoMoney.Service.Infrastructure.Eventing;
 
 namespace MoMoney.Modules
 {
-    public class NavigationModule : IModule, IEventSubscriber<NewProjectOpened>
+    public class NavigationModule : IModule, EventSubscriber<NewProjectOpened>
     {
         IRunPresenterCommand command;
 
product/client/boot/Modules/ToolbarModule.cs
@@ -9,15 +9,15 @@ namespace MoMoney.Modules
 {
     public class ToolbarModule :
         IModule,
-        IEventSubscriber<NewProjectOpened>,
-        IEventSubscriber<ClosingProjectEvent>,
-        IEventSubscriber<SavedChangesEvent>,
-        IEventSubscriber<UnsavedChangesEvent>
+        EventSubscriber<NewProjectOpened>,
+        EventSubscriber<ClosingProjectEvent>,
+        EventSubscriber<SavedChangesEvent>,
+        EventSubscriber<UnsavedChangesEvent>
     {
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
         readonly IRunPresenterCommand command;
 
-        public ToolbarModule(IEventAggregator broker, IRunPresenterCommand command)
+        public ToolbarModule(EventAggregator broker, IRunPresenterCommand command)
         {
             this.broker = broker;
             this.command = command;
product/client/boot/boot.csproj
@@ -105,6 +105,7 @@
     </Compile>
     <Compile Include="boot\container\registration\auto_wire_components_in_to_the.cs" />
     <Compile Include="boot\container\registration\auto_wire_components_in_to_the_specs.cs" />
+    <Compile Include="boot\container\registration\IContainerStartup.cs" />
     <Compile Include="boot\container\registration\IStartupCommand.cs" />
     <Compile Include="boot\container\registration\mapping\Mappers.cs" />
     <Compile Include="boot\container\registration\mapping\DelegateTargetAction.cs" />
product/client/presentation/Core/ApplicationController.cs
@@ -5,23 +5,23 @@ namespace MoMoney.Presentation.Core
 {
     public interface IApplicationController
     {
-        void run<Presenter>() where Presenter : IPresenter;
+        void run<Presenter>() where Presenter : Core.Presenter;
     }
 
     public class ApplicationController : IApplicationController
     {
-        IShell shell;
+        Shell shell;
         PresenterFactory presenter_factory;
-        IEventAggregator broker;
+        EventAggregator broker;
 
-        public ApplicationController(IShell shell, PresenterFactory presenter_factory, IEventAggregator broker)
+        public ApplicationController(Shell shell, PresenterFactory presenter_factory, EventAggregator broker)
         {
             this.presenter_factory = presenter_factory;
             this.broker = broker;
             this.shell = shell;
         }
 
-        public void run<Presenter>() where Presenter : IPresenter
+        public void run<Presenter>() where Presenter : Core.Presenter
         {
             var presenter = presenter_factory.create<Presenter>();
             broker.subscribe(presenter);
product/client/presentation/Core/ApplicationControllerSpecs.cs
@@ -12,10 +12,10 @@ namespace MoMoney.Presentation.Core
             context c = () =>
                         {
                             presenter_factory = the_dependency<PresenterFactory>();
-                            shell = the_dependency<IShell>();
+                            shell = the_dependency<Shell>();
                         };
 
-            static protected IShell shell;
+            static protected Shell shell;
             static protected PresenterFactory presenter_factory;
         }
 
@@ -23,18 +23,18 @@ namespace MoMoney.Presentation.Core
         {
             context c = () =>
                         {
-                            implementation_of_the_presenter = an<IPresenter>();
+                            implementation_of_the_presenter = an<Presenter>();
                             presenter_factory
-                                .is_told_to(r => r.create<IPresenter>())
+                                .is_told_to(r => r.create<Presenter>())
                                 .it_will_return(implementation_of_the_presenter);
                         };
 
-            because b = () => sut.run<IPresenter>();
+            because b = () => sut.run<Presenter>();
 
             it should_initialize_the_presenter_to_run =
                 () => implementation_of_the_presenter.was_told_to(p => p.present(shell));
 
-            static IPresenter implementation_of_the_presenter;
+            static Presenter implementation_of_the_presenter;
         }
     }
 }
\ No newline at end of file
product/client/presentation/Core/CachedPresenterFactory.cs
@@ -1,10 +1,11 @@
+using Gorilla.Commons.Infrastructure.Logging;
 using gorilla.commons.utility;
 
 namespace MoMoney.Presentation.Core
 {
     public interface PresenterFactory
     {
-        Presenter create<Presenter>() where Presenter : IPresenter;
+        Presenter create<Presenter>() where Presenter : Core.Presenter;
     }
 
     public class CachedPresenterFactory : PresenterFactory
@@ -18,10 +19,12 @@ namespace MoMoney.Presentation.Core
             this.view_factory = view_factory;
         }
 
-        public Presenter create<Presenter>() where Presenter : IPresenter
+        public Presenter create<Presenter>() where Presenter : Core.Presenter
         {
-            var presenter = presenters.find_an_implementation_of<IPresenter, Presenter>();
-            view_factory.create_for<Presenter>().attach_to(presenter);
+            var presenter = presenters.find_an_implementation_of<Core.Presenter, Presenter>();
+            var view = view_factory.create_for<Presenter>();
+            this.log().debug("attaching {0} to {1}", view, presenter);
+            view.attach_to(presenter);
             return presenter;
         }
     }
product/client/presentation/Core/CachingViewFactory.cs
@@ -1,6 +1,7 @@
 using System;
 using System.ComponentModel;
 using System.Linq;
+using Gorilla.Commons.Infrastructure.Logging;
 using gorilla.commons.utility;
 using momoney.presentation.views;
 
@@ -8,7 +9,7 @@ namespace MoMoney.Presentation.Core
 {
     public interface ViewFactory
     {
-        IView<Presenter> create_for<Presenter>() where Presenter : IPresenter;
+        IView<Presenter> create_for<Presenter>() where Presenter : Core.Presenter;
     }
 
     public class CachingViewFactory : ViewFactory
@@ -20,17 +21,20 @@ namespace MoMoney.Presentation.Core
             this.views = views;
         }
 
-        public IView<Presenter> create_for<Presenter>() where Presenter : IPresenter
+        public IView<Presenter> create_for<Presenter>() where Presenter : Core.Presenter
         {
             if (views.all().Any(x => typeof (IView<Presenter>).IsAssignableFrom(x.GetType())))
             {
                 return views.find_an_implementation_of<IView, IView<Presenter>>();
             }
-            return new NullView<Presenter>();
+            this.log().debug("cannot find a view for {0}", typeof (Presenter));
+            return Null<Presenter>.View;
         }
 
-        class NullView<T> : IView<T> where T : IPresenter
+        class Null<T> : IView<T> where T : Presenter
         {
+            static public readonly IView<T> View = new Null<T>();
+
             public void attach_to(T presenter)
             {
             }
product/client/presentation/Core/DialogPresenter.cs
@@ -0,0 +1,4 @@
+namespace MoMoney.Presentation.Core
+{
+    public interface DialogPresenter : Presenter { }
+}
\ No newline at end of file
product/client/presentation/Core/IContentPresenter.cs
@@ -1,6 +1,6 @@
 namespace MoMoney.Presentation.Core
 {
-    public interface IContentPresenter : IPresenter
+    public interface IContentPresenter : Presenter
     {
     }
 }
\ No newline at end of file
product/client/presentation/Core/IPresenter.cs → product/client/presentation/Core/Presenter.cs
@@ -2,8 +2,8 @@ using MoMoney.Presentation.Views;
 
 namespace MoMoney.Presentation.Core
 {
-    public interface IPresenter
+    public interface Presenter
     {
-        void present(IShell shell);
+        void present(Shell shell);
     }
 }
\ No newline at end of file
product/client/presentation/Core/PresenterRegistry.cs
@@ -4,23 +4,23 @@ using gorilla.commons.utility;
 
 namespace MoMoney.Presentation.Core
 {
-    public interface IPresenterRegistry : Registry<IPresenter> {}
+    public interface IPresenterRegistry : Registry<Presenter> {}
 
     public class PresenterRegistry : IPresenterRegistry
     {
-        readonly Registry<IPresenter> presenters;
+        readonly Registry<Presenter> presenters;
 
-        public PresenterRegistry(Registry<IPresenter> presenters)
+        public PresenterRegistry(Registry<Presenter> presenters)
         {
             this.presenters = presenters;
         }
 
-        public IEnumerable<IPresenter> all()
+        public IEnumerable<Presenter> all()
         {
             return presenters.all();
         }
 
-        public IEnumerator<IPresenter> GetEnumerator()
+        public IEnumerator<Presenter> GetEnumerator()
         {
             return all().GetEnumerator();
         }
product/client/presentation/Core/ContentPresenter.cs → product/client/presentation/Core/TabPresenter.cs
@@ -3,11 +3,11 @@ using MoMoney.Presentation.Views;
 
 namespace MoMoney.Presentation.Core
 {
-    public abstract class ContentPresenter<T> : IContentPresenter where T : IDockedContentView
+    public abstract class TabPresenter<T> : IContentPresenter where T : IDockedContentView
     {
         protected readonly T view;
 
-        protected ContentPresenter(T view)
+        protected TabPresenter(T view)
         {
             this.view = view;
         }
@@ -16,7 +16,7 @@ namespace MoMoney.Presentation.Core
         {
         }
 
-        public void present(IShell shell)
+        public void present(Shell shell)
         {
             shell.add(view);
             present();
product/client/presentation/Model/Menu/File/CloseWindowCommand.cs
@@ -7,9 +7,9 @@ namespace momoney.presentation.model.menu.file
 
     public class CloseWindowCommand : ICloseWindowCommand
     {
-        readonly IShell shell;
+        readonly Shell shell;
 
-        public CloseWindowCommand(IShell shell)
+        public CloseWindowCommand(Shell shell)
         {
             this.shell = shell;
         }
product/client/presentation/Model/Menu/File/ExitCommand.cs
@@ -13,10 +13,10 @@ namespace momoney.presentation.model.menu.file
     public class ExitCommand : IExitCommand
     {
         readonly IApplication application;
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
         readonly ISaveChangesCommand command;
 
-        public ExitCommand(IApplication application, IEventAggregator broker, ISaveChangesCommand command)
+        public ExitCommand(IApplication application, EventAggregator broker, ISaveChangesCommand command)
         {
             this.application = application;
             this.command = command;
product/client/presentation/Model/Menu/File/ExitCommandSpecs.cs
@@ -18,12 +18,12 @@ namespace momoney.presentation.model.menu.file
         context c = () =>
         {
             application = the_dependency<IApplication>();
-            broker = the_dependency<IEventAggregator>();
+            broker = the_dependency<EventAggregator>();
             save_changes_command = the_dependency<ISaveChangesCommand>();
         };
 
         protected static IApplication application;
-        protected static IEventAggregator broker;
+        protected static EventAggregator broker;
         protected static ISaveChangesCommand save_changes_command;
     }
 
product/client/presentation/Model/Menu/File/SaveChangesPresenter.cs
@@ -7,7 +7,7 @@ using MoMoney.Presentation.Views;
 
 namespace MoMoney.Presentation.Model.Menu.File
 {
-    public class SaveChangesPresenter : ISaveChangesCommand, IPresenter
+    public class SaveChangesPresenter : ISaveChangesCommand, DialogPresenter
     {
         readonly IProjectController current_project;
         readonly ISaveChangesView view;
@@ -25,7 +25,7 @@ namespace MoMoney.Presentation.Model.Menu.File
             this.view = view;
         }
 
-        public virtual void present(IShell shell)
+        public virtual void present(Shell shell)
         {
             throw new NotImplementedException();
         }
product/client/presentation/Model/Menu/MenuItemBuilder.cs
@@ -21,7 +21,7 @@ namespace MoMoney.Presentation.Model.Menu
     public class MenuItemBuilder : IMenuItemBuilder
     {
         readonly DependencyRegistry registry;
-        readonly IEventAggregator aggregator;
+        readonly EventAggregator aggregator;
         readonly CommandProcessor processor;
 
         string name_of_the_menu { get; set; }
@@ -30,7 +30,7 @@ namespace MoMoney.Presentation.Model.Menu
         ShortcutKey key { get; set; }
         Func<bool> can_be_clicked = () => true;
 
-        public MenuItemBuilder(DependencyRegistry registry, IEventAggregator aggregator, CommandProcessor processor)
+        public MenuItemBuilder(DependencyRegistry registry, EventAggregator aggregator, CommandProcessor processor)
         {
             name_of_the_menu = "Unknown";
             command_to_execute = () => {};
product/client/presentation/Model/Menu/ToolBarItemBuilder.cs
@@ -14,7 +14,7 @@ namespace MoMoney.Presentation.Model.Menu
         readonly CommandProcessor processor;
         Func<bool> the_condition;
 
-        public ToolBarItemBuilder(DependencyRegistry registry, IEventAggregator aggregator, CommandProcessor processor)
+        public ToolBarItemBuilder(DependencyRegistry registry, EventAggregator aggregator, CommandProcessor processor)
         {
             this.registry = registry;
             this.processor = processor;
product/client/presentation/Model/Projects/ProjectController.cs
@@ -10,12 +10,12 @@ namespace MoMoney.Presentation.Model.Projects
 {
     public class ProjectController : IProjectController, Callback<IUnitOfWork>
     {
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
         readonly IProjectTasks configuration;
         IProject project;
         bool unsaved_changes = false;
 
-        public ProjectController(IEventAggregator broker, IProjectTasks configuration)
+        public ProjectController(EventAggregator broker, IProjectTasks configuration)
         {
             this.broker = broker;
             this.configuration = configuration;
product/client/presentation/Model/Projects/ProjectControllerSpecs.cs
@@ -17,11 +17,11 @@ namespace MoMoney.Presentation.Model.Projects
         {
             context c = () =>
             {
-                broker = the_dependency<IEventAggregator>();
+                broker = the_dependency<EventAggregator>();
                 tasks = the_dependency<IProjectTasks>();
             };
 
-            static protected IEventAggregator broker;
+            static protected EventAggregator broker;
             static protected IProjectTasks tasks;
         }
 
product/client/presentation/Presenters/AboutTheApplicationPresenter.cs
@@ -3,7 +3,7 @@ using momoney.presentation.views;
 
 namespace momoney.presentation.presenters
 {
-    public class AboutTheApplicationPresenter : ContentPresenter<IAboutApplicationView>
+    public class AboutTheApplicationPresenter : TabPresenter<IAboutApplicationView>
     {
         public AboutTheApplicationPresenter(IAboutApplicationView view) : base(view)
         {
product/client/presentation/Presenters/AddBillPaymentPresenter.cs
@@ -7,7 +7,7 @@ using MoMoney.Service.Contracts.Application;
 
 namespace momoney.presentation.presenters
 {
-    public class AddBillPaymentPresenter : ContentPresenter<IAddBillPaymentView>
+    public class AddBillPaymentPresenter : TabPresenter<IAddBillPaymentView>
     {
         readonly ICommandPump pump;
 
product/client/presentation/Presenters/AddCompanyPresenter.cs
@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using Gorilla.Commons.Infrastructure.Logging;
 using MoMoney.DTO;
 using MoMoney.Presentation.Core;
 using MoMoney.Presentation.Views;
@@ -6,7 +7,7 @@ using MoMoney.Service.Contracts.Application;
 
 namespace MoMoney.Presentation.Presenters
 {
-    public class AddCompanyPresenter : ContentPresenter<IAddCompanyView>
+    public class AddCompanyPresenter : TabPresenter<IAddCompanyView>
     {
         readonly ICommandPump pump;
 
@@ -22,6 +23,7 @@ namespace MoMoney.Presentation.Presenters
 
         public void submit(RegisterNewCompany dto)
         {
+            this.log().debug("registering a new company: {0}", dto.company_name);
             pump.run<IRegisterNewCompanyCommand, RegisterNewCompany>(dto);
             pump.run<IEnumerable<CompanyDTO>, IGetAllCompanysQuery>(view);
         }
product/client/presentation/Presenters/AddNewIncomePresenter.cs
@@ -6,7 +6,7 @@ using MoMoney.Service.Contracts.Application;
 
 namespace MoMoney.Presentation.Presenters
 {
-    public class AddNewIncomePresenter : ContentPresenter<IAddNewIncomeView>
+    public class AddNewIncomePresenter : TabPresenter<IAddNewIncomeView>
     {
         readonly ICommandPump pump;
 
product/client/presentation/Presenters/AddNewIncomePresenterSpecs.cs
@@ -47,10 +47,10 @@ namespace momoney.presentation.presenters
             () => pump.was_told_to(x => x.run<IEnumerable<IncomeInformationDTO>, IGetAllIncomeQuery>(view));
 
         context c = () => {
-                              shell = an<IShell>();
+                              shell = an<Shell>();
         };
 
         because b = () => sut.present(shell);
-        static IShell shell;
+        static Shell shell;
     }
 }
\ No newline at end of file
product/client/presentation/Presenters/ApplicationMenuPresenter.cs
@@ -6,7 +6,7 @@ using MoMoney.Presentation.Views;
 
 namespace momoney.presentation.presenters
 {
-    public class ApplicationMenuPresenter : IPresenter
+    public class ApplicationMenuPresenter : Presenter
     {
         ISubMenuRegistry registry;
 
@@ -15,7 +15,7 @@ namespace momoney.presentation.presenters
             this.registry = registry;
         }
 
-        public void present(IShell shell)
+        public void present(Shell shell)
         {
             shell.region<MenuStrip>(x => registry.all().each(y => y.add_to(x)));
         }
product/client/presentation/Presenters/ApplicationShellPresenter.cs
@@ -7,7 +7,7 @@ using MoMoney.Service.Infrastructure.Eventing;
 
 namespace momoney.presentation.presenters
 {
-    public class ApplicationShellPresenter : IPresenter, IEventSubscriber<ClosingProjectEvent>
+    public class ApplicationShellPresenter : Presenter, EventSubscriber<ClosingProjectEvent>
     {
         IExitCommand command;
 
@@ -24,7 +24,7 @@ namespace momoney.presentation.presenters
             this.command = command;
         }
 
-        public virtual void present(IShell shell)
+        public virtual void present(Shell shell)
         {
             shutdown = () =>
                        {
product/client/presentation/Presenters/CheckForUpdatesPresenter.cs
@@ -9,7 +9,7 @@ using momoney.service.infrastructure.updating;
 
 namespace momoney.presentation.presenters
 {
-    public class CheckForUpdatesPresenter : IPresenter, Callback<Percent>
+    public class CheckForUpdatesPresenter : DialogPresenter, Callback<Percent>
     {
         readonly ICheckForUpdatesView view;
         readonly ICommandPump pump;
@@ -20,7 +20,7 @@ namespace momoney.presentation.presenters
             this.view = view;
         }
 
-        public void present(IShell shell)
+        public void present(Shell shell)
         {
             pump.run<ApplicationVersion, IWhatIsTheAvailableVersion>(view);
             view.display();
product/client/presentation/Presenters/CheckForUpdatesPresenterSpecs.cs
@@ -32,10 +32,10 @@ namespace momoney.presentation.presenters
 
         context c = () =>
                     {
-                        shell = an<IShell>();
+                        shell = an<Shell>();
                     };
         because b = () => sut.present(shell);
-        static IShell shell;
+        static Shell shell;
     }
 
     public class when_initiating_an_update_and_one_is_available : behaves_like_check_for_updates_presenter
product/client/presentation/Presenters/CommandFactory.cs
@@ -1,26 +1,9 @@
 using gorilla.commons.utility;
-using momoney.presentation.presenters;
-using momoney.service.infrastructure.threading;
 
 namespace MoMoney.Presentation.Presenters
 {
-    public interface ICommandFactory
+    public interface CommandFactory
     {
         Command create_for<T>(Callback<T> item, Query<T> query);
     }
-
-    public class CommandFactory : ICommandFactory
-    {
-        readonly ISynchronizationContextFactory factory;
-
-        public CommandFactory(ISynchronizationContextFactory factory)
-        {
-            this.factory = factory;
-        }
-
-        public Command create_for<T>(Callback<T> item, Query<T> query)
-        {
-            return new RunQueryCommand<T>(item, new ProcessQueryCommand<T>(query, factory));
-        }
-    }
 }
\ No newline at end of file
product/client/presentation/Presenters/CommandPump.cs
@@ -1,4 +1,5 @@
 using Gorilla.Commons.Infrastructure.Container;
+using Gorilla.Commons.Infrastructure.Logging;
 using gorilla.commons.utility;
 using MoMoney.Service.Infrastructure.Threading;
 
@@ -15,9 +16,9 @@ namespace MoMoney.Presentation.Presenters
     {
         readonly CommandProcessor processor;
         readonly DependencyRegistry registry;
-        readonly ICommandFactory factory;
+        readonly CommandFactory factory;
 
-        public CommandPump(CommandProcessor processor, DependencyRegistry registry, ICommandFactory factory)
+        public CommandPump(CommandProcessor processor, DependencyRegistry registry, CommandFactory factory)
         {
             this.processor = processor;
             this.factory = factory;
@@ -37,11 +38,14 @@ namespace MoMoney.Presentation.Presenters
 
         public ICommandPump run<Command, T>(T input) where Command : ParameterizedCommand<T>
         {
-            processor.add(() => registry.get_a<Command>().run(input));
+            var cached = input;
+            var command = registry.get_a<Command>();
+            this.log().debug("found: {0}", command);
+            processor.add(() => command.run(cached));
             return this;
         }
 
-        public ICommandPump run<T>(Callback<T> item, Query<T> query)
+        ICommandPump run<T>(Callback<T> item, Query<T> query)
         {
             return run(factory.create_for(item, query));
         }
product/client/presentation/Presenters/GettingStartedPresenter.cs
@@ -3,7 +3,7 @@ using momoney.presentation.views;
 
 namespace momoney.presentation.presenters
 {
-    public class GettingStartedPresenter : ContentPresenter<IGettingStartedView>
+    public class GettingStartedPresenter : TabPresenter<IGettingStartedView>
     {
         public GettingStartedPresenter(IGettingStartedView view) : base(view)
         {
product/client/presentation/Presenters/GettingStartedPresenterSpecs.cs
@@ -23,11 +23,11 @@ namespace momoney.presentation.presenters
 
             context c = () =>
                         {
-                            shell = an<IShell>();
+                            shell = an<Shell>();
                         };
 
             because b = () => sut.present(shell);
-            static IShell shell;
+            static Shell shell;
         }
     }
 }
\ No newline at end of file
product/client/presentation/Presenters/IRunPresenterCommand.cs
@@ -1,9 +1,7 @@
-using MoMoney.Presentation.Core;
-
 namespace MoMoney.Presentation.Presenters
 {
     public interface IRunPresenterCommand
     {
-        void run<Presenter>() where Presenter : IPresenter;
+        void run<Presenter>() where Presenter : Core.Presenter;
     }
 }
\ No newline at end of file
product/client/presentation/Presenters/LogFilePresenter.cs
@@ -4,7 +4,7 @@ using momoney.service.infrastructure.logging;
 
 namespace momoney.presentation.presenters
 {
-    public class LogFilePresenter : ContentPresenter<ILogFileView>
+    public class LogFilePresenter : TabPresenter<ILogFileView>
     {
         ILogFileTasks tasks;
 
product/client/presentation/Presenters/LogFileViewPresenterSpecs.cs
@@ -24,7 +24,7 @@ namespace momoney.presentation.presenters
 
         context c = () =>
         {
-            shell = an<IShell>();
+            shell = an<Shell>();
             log_file_path = "log.txt";
             log_file_contents = "hello_jello";
             tasks.is_told_to(x => x.get_the_path_to_the_log_file()).it_will_return(log_file_path);
@@ -35,6 +35,6 @@ namespace momoney.presentation.presenters
 
         static string log_file_contents;
         static string log_file_path;
-        static IShell shell;
+        static Shell shell;
     }
 }
\ No newline at end of file
product/client/presentation/Presenters/MainMenuPresenter.cs
@@ -6,7 +6,7 @@ using MoMoney.Presentation.Views;
 
 namespace MoMoney.Presentation.Presenters
 {
-    public class MainMenuPresenter : ContentPresenter<IMainMenuView>
+    public class MainMenuPresenter : TabPresenter<IMainMenuView>
     {
         IRunPresenterCommand command;
 
product/client/presentation/Presenters/NavigationPresenter.cs
@@ -4,7 +4,7 @@ using momoney.presentation.views;
 
 namespace momoney.presentation.presenters
 {
-    public class NavigationPresenter : ContentPresenter<INavigationView>
+    public class NavigationPresenter : TabPresenter<INavigationView>
     {
         readonly INavigationTreeVisitor tree_view_visitor;
 
product/client/presentation/Presenters/NavigationPresenterSpecs.cs
@@ -13,7 +13,7 @@ namespace momoney.presentation.presenters
 
         context c = () =>
         {
-            shell = an<IShell>();
+            shell = an<Shell>();
             view = the_dependency<INavigationView>();
             tree_view_visitor = the_dependency<INavigationTreeVisitor>();
         };
@@ -22,6 +22,6 @@ namespace momoney.presentation.presenters
 
         static INavigationView view;
         static INavigationTreeVisitor tree_view_visitor;
-        static IShell shell;
+        static Shell shell;
     }
 }
\ No newline at end of file
product/client/presentation/Presenters/NotificationIconModule.cs
@@ -8,8 +8,8 @@ using MoMoney.Service.Infrastructure.Eventing;
 namespace momoney.presentation.presenters
 {
     public class NotificationIconModule : IModule,
-                                          IEventSubscriber<ClosingTheApplication>,
-                                          IEventSubscriber<NewProjectOpened>
+                                          EventSubscriber<ClosingTheApplication>,
+                                          EventSubscriber<NewProjectOpened>
     {
         readonly INotificationIconView view;
 
product/client/presentation/Presenters/ReportPresenter.cs
@@ -6,7 +6,7 @@ using MoMoney.Presentation.Views;
 
 namespace MoMoney.Presentation.Presenters
 {
-    public class ReportPresenter<Report, T, Query> : ContentPresenter<IReportViewer>
+    public class ReportPresenter<Report, T, Query> : TabPresenter<IReportViewer>
         where Report : IBindReportTo<T, Query>
         where Query : Query<T>
     {
product/client/presentation/Presenters/RestartCommand.cs
@@ -10,9 +10,9 @@ namespace momoney.presentation.presenters
     public class RestartCommand : IRestartCommand
     {
         readonly IApplication application;
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
 
-        public RestartCommand(IApplication application, IEventAggregator broker)
+        public RestartCommand(IApplication application, EventAggregator broker)
         {
             this.application = application;
             this.broker = broker;
product/client/presentation/Presenters/RunPresenterCommand.cs
@@ -11,7 +11,7 @@ namespace MoMoney.Presentation.Presenters
             this.application_controller = application_controller;
         }
 
-        public void run<Presenter>() where Presenter : IPresenter
+        public void run<Presenter>() where Presenter : Core.Presenter
         {
             application_controller.run<Presenter>();
         }
product/client/presentation/Presenters/RunQueryCommand.cs
@@ -3,9 +3,7 @@ using MoMoney.Presentation.Presenters;
 
 namespace momoney.presentation.presenters
 {
-    public interface IRunQueryCommand<T> : Command {}
-
-    public class RunQueryCommand<T> : IRunQueryCommand<T>
+    public class RunQueryCommand<T> : Command
     {
         readonly Callback<T> callback;
         readonly IProcessQueryCommand<T> command;
product/client/presentation/Presenters/RunThe.cs
@@ -4,9 +4,9 @@ using MoMoney.Service.Infrastructure.Threading;
 
 namespace momoney.presentation.presenters
 {
-    public interface IRunThe<TPresenter> : Command where TPresenter : IPresenter {}
+    public interface IRunThe<TPresenter> : Command where TPresenter : Presenter {}
 
-    public class RunThe<TPresenter> : IRunThe<TPresenter> where TPresenter : IPresenter
+    public class RunThe<TPresenter> : IRunThe<TPresenter> where TPresenter : Presenter
     {
         readonly IApplicationController controller;
         readonly CommandProcessor processor;
product/client/presentation/Presenters/RunTheSpecs.cs
@@ -11,10 +11,10 @@ namespace momoney.presentation.presenters
         [Ignore]
         [Concern(typeof (RunThe<>))]
         public class when_initializing_different_regions_of_the_user_interface :
-            concerns_for<IRunThe<IPresenter>, RunThe<IPresenter>>
+            concerns_for<IRunThe<Presenter>, RunThe<Presenter>>
         {
             //it should_initialize_the_presenter_that_controls_that_region = () => controller.was_told_to(x => x.run<IPresenter>());
-            it should_initialize_the_presenter_that_controls_that_region = () => processor.was_told_to(x => x.add(() => controller.run<IPresenter>()));
+            it should_initialize_the_presenter_that_controls_that_region = () => processor.was_told_to(x => x.add(() => controller.run<Presenter>()));
 
             context c = () =>
             {
product/client/presentation/Presenters/StatusBarModule.cs
@@ -11,19 +11,19 @@ namespace MoMoney.Presentation.Presenters
 {
     public class StatusBarModule :
         IModule,
-        IEventSubscriber<SavedChangesEvent>,
-        IEventSubscriber<NewProjectOpened>,
-        IEventSubscriber<ClosingTheApplication>,
-        IEventSubscriber<UnsavedChangesEvent>,
-        IEventSubscriber<StartedRunningCommand>,
-        IEventSubscriber<FinishedRunningCommand>,
-        IEventSubscriber<ClosingProjectEvent>
+        EventSubscriber<SavedChangesEvent>,
+        EventSubscriber<NewProjectOpened>,
+        EventSubscriber<ClosingTheApplication>,
+        EventSubscriber<UnsavedChangesEvent>,
+        EventSubscriber<StartedRunningCommand>,
+        EventSubscriber<FinishedRunningCommand>,
+        EventSubscriber<ClosingProjectEvent>
     {
         readonly IStatusBarView view;
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
         readonly ITimer timer;
 
-        public StatusBarModule(IStatusBarView view, IEventAggregator broker, ITimer timer)
+        public StatusBarModule(IStatusBarView view, EventAggregator broker, ITimer timer)
         {
             this.view = view;
             this.broker = broker;
product/client/presentation/Presenters/SynchronizedCommandFactory.cs
@@ -0,0 +1,21 @@
+using gorilla.commons.utility;
+using momoney.presentation.presenters;
+using momoney.service.infrastructure.threading;
+
+namespace MoMoney.Presentation.Presenters
+{
+    public class SynchronizedCommandFactory : CommandFactory
+    {
+        readonly ISynchronizationContextFactory factory;
+
+        public SynchronizedCommandFactory(ISynchronizationContextFactory factory)
+        {
+            this.factory = factory;
+        }
+
+        public Command create_for<T>(Callback<T> item, Query<T> query)
+        {
+            return new RunQueryCommand<T>(item, new ProcessQueryCommand<T>(query, factory));
+        }
+    }
+}
\ No newline at end of file
product/client/presentation/Presenters/TaskTrayPresenter.cs
@@ -8,10 +8,10 @@ namespace momoney.presentation.presenters
 {
     public class TaskTrayPresenter :
         IModule,
-        IEventSubscriber<SavedChangesEvent>,
-        IEventSubscriber<StartedRunningCommand>,
-        IEventSubscriber<FinishedRunningCommand>,
-        IEventSubscriber<NewProjectOpened>
+        EventSubscriber<SavedChangesEvent>,
+        EventSubscriber<StartedRunningCommand>,
+        EventSubscriber<FinishedRunningCommand>,
+        EventSubscriber<NewProjectOpened>
     {
         readonly ITaskTrayMessageView view;
 
product/client/presentation/Presenters/TitleBarPresenter.cs
@@ -8,10 +8,10 @@ namespace momoney.presentation.presenters
 {
     public class TitleBarPresenter :
         IModule,
-        IEventSubscriber<UnsavedChangesEvent>,
-        IEventSubscriber<SavedChangesEvent>,
-        IEventSubscriber<NewProjectOpened>,
-        IEventSubscriber<ClosingProjectEvent>
+        EventSubscriber<UnsavedChangesEvent>,
+        EventSubscriber<SavedChangesEvent>,
+        EventSubscriber<NewProjectOpened>,
+        EventSubscriber<ClosingProjectEvent>
     {
         readonly ITitleBar view;
         readonly IProjectController project;
product/client/presentation/Presenters/TitleBarPresenterSpecs.cs
@@ -14,11 +14,11 @@ namespace momoney.presentation.presenters
         {
             project = the_dependency<IProjectController>();
             view = the_dependency<ITitleBar>();
-            broker = the_dependency<IEventAggregator>();
+            broker = the_dependency<EventAggregator>();
         };
 
         protected static ITitleBar view;
-        protected static IEventAggregator broker;
+        protected static EventAggregator broker;
         protected static IProjectController project;
     }
 
product/client/presentation/Presenters/ToolBarPresenter.cs
@@ -11,7 +11,7 @@ using MoMoney.Presentation.Winforms.Resources;
 
 namespace momoney.presentation.presenters
 {
-    public class ToolBarPresenter : IPresenter
+    public class ToolBarPresenter : Presenter
     {
         IRegionManager shell;
         IProjectController project;
@@ -22,7 +22,7 @@ namespace momoney.presentation.presenters
             this.project = project;
         }
 
-        public void present(IShell shell)
+        public void present(Shell shell)
         {
             shell.region<ToolStrip>(x => buttons().each(y => y.add_to(x)));
         }
product/client/presentation/Presenters/UnhandledErrorPresenter.cs
@@ -7,7 +7,7 @@ using MoMoney.Service.Infrastructure.Eventing;
 
 namespace momoney.presentation.presenters
 {
-    public class UnhandledErrorPresenter : IModule, IPresenter, IEventSubscriber<UnhandledErrorOccurred>
+    public class UnhandledErrorPresenter : IModule, Presenter, EventSubscriber<UnhandledErrorOccurred>
     {
         readonly IUnhandledErrorView view;
         readonly IRestartCommand restart;
@@ -18,7 +18,7 @@ namespace momoney.presentation.presenters
             restart = command;
         }
 
-        public void present(IShell shell)
+        public void present(Shell shell)
         {
         }
 
product/client/presentation/Presenters/UnhandledErrorPresenterSpecs.cs
@@ -12,11 +12,11 @@ namespace momoney.presentation.presenters
         context c = () =>
         {
             view = the_dependency<IUnhandledErrorView>();
-            broker = the_dependency<IEventAggregator>();
+            broker = the_dependency<EventAggregator>();
         };
 
         protected static IUnhandledErrorView view;
-        protected static IEventAggregator broker;
+        protected static EventAggregator broker;
     }
 
     public class when_an_error_occurs_in_the_application : behaves_like_unhandled_error_presenter
product/client/presentation/Presenters/ViewAllBillsPresenter.cs
@@ -7,7 +7,7 @@ using MoMoney.Service.Contracts.Application;
 
 namespace momoney.presentation.presenters
 {
-    public class ViewAllBillsPresenter : ContentPresenter<IViewAllBills>
+    public class ViewAllBillsPresenter : TabPresenter<IViewAllBills>
     {
         readonly ICommandPump pump;
 
product/client/presentation/Presenters/ViewIncomeHistoryPresenter.cs
@@ -6,7 +6,7 @@ using MoMoney.Service.Contracts.Application;
 
 namespace MoMoney.Presentation.Presenters
 {
-    public class ViewIncomeHistoryPresenter : ContentPresenter<IViewIncomeHistory>
+    public class ViewIncomeHistoryPresenter : TabPresenter<IViewIncomeHistory>
     {
         readonly ICommandPump pump;
 
product/client/presentation/Views/IApplicationDockedWindow.cs
@@ -4,7 +4,7 @@ using WeifenLuo.WinFormsUI.Docking;
 
 namespace MoMoney.Presentation.Views
 {
-    public interface IApplicationDockedWindow : IWindowEvents, IDockedContentView
+    public interface IApplicationDockedWindow : IDockedContentView
     {
         IApplicationDockedWindow titled(string title, params object[] arguments);
         IApplicationDockedWindow icon(ApplicationIcon icon);
product/client/presentation/Views/ICheckForUpdatesView.cs
@@ -5,7 +5,7 @@ using momoney.service.infrastructure.updating;
 
 namespace momoney.presentation.views
 {
-    public interface ICheckForUpdatesView : IView<CheckForUpdatesPresenter>, Callback<ApplicationVersion>
+    public interface ICheckForUpdatesView : IDialog<CheckForUpdatesPresenter>, Callback<ApplicationVersion>
     {
         void display();
         void downloaded(Percent percentage_complete);
product/client/presentation/Views/IDialog.cs
@@ -0,0 +1,8 @@
+using MoMoney.Presentation.Core;
+
+namespace momoney.presentation.views
+{
+    public interface IDialog<Presenter> : IView<Presenter> where Presenter : DialogPresenter
+    {
+    }
+}
\ No newline at end of file
product/client/presentation/Views/ISaveChangesView.cs
@@ -2,7 +2,7 @@ using MoMoney.Presentation.Model.Menu.File;
 
 namespace momoney.presentation.views
 {
-    public interface ISaveChangesView : IView<SaveChangesPresenter>
+    public interface ISaveChangesView : IDialog<SaveChangesPresenter>
     {
         void prompt_user_to_save();
     }
product/client/presentation/Views/IView.cs
@@ -1,15 +1,13 @@
 using System;
 using System.ComponentModel;
-using MoMoney.Presentation.Core;
-using MoMoney.Presentation.Views;
 
 namespace momoney.presentation.views
 {
-    public interface IView : IWindowEvents, ISynchronizeInvoke, IDisposable
+    public interface IView : ISynchronizeInvoke, IDisposable
     {
     }
 
-    public interface IView<Presenter> : IView where Presenter : IPresenter
+    public interface IView<Presenter> : IView where Presenter : MoMoney.Presentation.Core.Presenter
     {
         void attach_to(Presenter presenter);
     }
product/client/presentation/Views/IWindowEvents.cs
@@ -1,14 +0,0 @@
-using System;
-using System.ComponentModel;
-using momoney.presentation.views;
-
-namespace MoMoney.Presentation.Views
-{
-    public interface IWindowEvents
-    {
-        ControlAction<EventArgs> activated { get; set; }
-        ControlAction<EventArgs> deactivated { get; set; }
-        ControlAction<EventArgs> closed { get; set; }
-        ControlAction<CancelEventArgs> closing { get; set; }
-    }
-}
\ No newline at end of file
product/client/presentation/Views/IShell.cs → product/client/presentation/Views/Shell.cs
@@ -5,7 +5,7 @@ using momoney.presentation.views;
 
 namespace MoMoney.Presentation.Views
 {
-    public interface IShell : IWin32Window, ISynchronizeInvoke, IContainerControl, IBindableComponent, IDropTarget,
+    public interface Shell : IWin32Window, ISynchronizeInvoke, IContainerControl, IBindableComponent, IDropTarget,
                               IRegionManager
     {
         void attach_to(ApplicationShellPresenter presenter);
product/client/presentation/Winforms/Views/AddCompanyView.cs
@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Windows.Forms;
+using Gorilla.Commons.Infrastructure.Logging;
 using MoMoney.DTO;
 using MoMoney.Presentation.Presenters;
 using momoney.presentation.views;
@@ -35,8 +36,13 @@ namespace MoMoney.Presentation.Winforms.Views
 
         public void attach_to(AddCompanyPresenter presenter)
         {
+            this.log().debug("attaching add company presenter");
             ux_company_name.bind_to(dto, x => x.company_name);
-            submit_button = x => presenter.submit(dto);
+            submit_button = x =>
+                            {
+                                this.log().debug("clicked on submit button");
+                                presenter.submit(dto);
+                            };
         }
 
         public void run(IEnumerable<CompanyDTO> companies)
product/client/presentation/Winforms/Views/ApplicationDockedWindow.cs
@@ -1,9 +1,6 @@
-using System;
-using System.ComponentModel;
 using System.Linq;
 using System.Windows.Forms;
 using gorilla.commons.utility;
-using momoney.presentation.views;
 using MoMoney.Presentation.Views;
 using MoMoney.Presentation.Winforms.Helpers;
 using MoMoney.Presentation.Winforms.Resources;
@@ -21,42 +18,8 @@ namespace MoMoney.Presentation.Winforms.Views
             Icon = ApplicationIcons.Application;
             dock_state = DockState.Document;
             HideOnClose = true;
-
-            activated = x => { };
-            deactivated = x => { };
-            closed = x => { };
-            closing = x => { };
-        }
-
-        protected override void OnActivated(EventArgs e)
-        {
-            base.OnActivated(e);
-            activated(e);
-        }
-
-        protected override void OnDeactivate(EventArgs e)
-        {
-            base.OnDeactivate(e);
-            deactivated(e);
         }
 
-        protected override void OnClosing(CancelEventArgs e)
-        {
-            base.OnClosing(e);
-            closing(e);
-        }
-
-        protected override void OnClosed(EventArgs e)
-        {
-            base.OnClosed(e);
-            closed(e);
-        }
-
-        public ControlAction<EventArgs> activated { get; set; }
-        public ControlAction<EventArgs> deactivated { get; set; }
-        public ControlAction<EventArgs> closed { get; set; }
-        public ControlAction<CancelEventArgs> closing { get; set; }
-
         public IApplicationDockedWindow create_tool_tip_for(string title, string caption, Control control)
         {
             var tip = new ToolTip {IsBalloon = true, ToolTipTitle = title};
@@ -94,36 +57,36 @@ namespace MoMoney.Presentation.Winforms.Views
         {
             using (new SuspendLayout(panel))
             {
-                if (window_is_already_contained_in(panel)) 
-                    remove_from(panel);
+                //if (window_is_already_contained_in(panel)) 
+                //    remove_from(panel);
 
                 Show(panel, dock_state);
             }
         }
 
-        void remove_from(DockPanel panel)
-        {
-            using (new SuspendLayout(panel))
-            {
-                var panel_to_remove = get_window_from(panel);
-                panel_to_remove.DockHandler.Close();
-                panel_to_remove.DockHandler.Dispose();
-            }
-        }
-
-        IDockContent get_window_from(DockPanel panel)
-        {
-            return panel.Documents.Single(matches);
-        }
-
-        bool window_is_already_contained_in(DockPanel panel)
-        {
-            return panel.Documents.Count(matches) > 0;
-        }
-
-        bool matches(IDockContent x)
-        {
-            return x.DockHandler.TabText.Equals(TabText);
-        }
+        //void remove_from(DockPanel panel)
+        //{
+        //    using (new SuspendLayout(panel))
+        //    {
+        //        //var panel_to_remove = get_window_from(panel);
+        //        //panel_to_remove.DockHandler.Close();
+        //        //panel_to_remove.DockHandler.Dispose();
+        //    }
+        //}
+
+        //IDockContent get_window_from(DockPanel panel)
+        //{
+        //    return panel.Documents.Single(matches);
+        //}
+
+        //bool window_is_already_contained_in(DockPanel panel)
+        //{
+        //    return panel.Documents.Count(matches) > 0;
+        //}
+
+        //bool matches(IDockContent x)
+        //{
+        //    return x.DockHandler.TabText.Equals(TabText);
+        //}
     }
 }
\ No newline at end of file
product/client/presentation/Winforms/Views/ApplicationShell.cs
@@ -11,8 +11,8 @@ using MoMoney.Presentation.Winforms.Helpers;
 
 namespace MoMoney.Presentation.Winforms.Views
 {
-    [Export(typeof (IShell))]
-    public partial class ApplicationShell : ApplicationWindow, IShell
+    [Export(typeof (Shell))]
+    public partial class ApplicationShell : ApplicationWindow, Shell
     {
         readonly IDictionary<string, IComponent> regions;
         ControlAction<EventArgs> closed_action = x => { };
product/client/presentation/Winforms/Views/ApplicationShellSpecs.cs
@@ -9,7 +9,7 @@ namespace MoMoney.Presentation.Winforms.Views
 {
     public class ApplicationShellSpecs
     {
-        public class concern : concerns_for<IShell, ApplicationShell>
+        public class concern : concerns_for<Shell, ApplicationShell>
         {
         }
 
product/client/presentation/Winforms/Views/ApplicationWindow.cs
@@ -1,5 +1,3 @@
-using System;
-using System.ComponentModel;
 using System.Windows.Forms;
 using momoney.presentation.views;
 using MoMoney.Presentation.Winforms.Helpers;
@@ -13,18 +11,8 @@ namespace MoMoney.Presentation.Winforms.Views
         {
             InitializeComponent();
             Icon = ApplicationIcons.Application;
-
-            activated = x => { };
-            deactivated = x => { };
-            closed = x => { };
-            closing = x => { };
         }
 
-        public ControlAction<EventArgs> activated { get; set; }
-        public ControlAction<EventArgs> deactivated { get; set; }
-        public ControlAction<EventArgs> closed { get; set; }
-        public ControlAction<CancelEventArgs> closing { get; set; }
-
         public IApplicationWindow create_tool_tip_for(string title, string caption, Control control)
         {
             var tip = new ToolTip {IsBalloon = true, ToolTipTitle = title};
@@ -53,29 +41,5 @@ namespace MoMoney.Presentation.Winforms.Views
             base.Text = "MoMoney (BETA) - " + title;
             return this;
         }
-
-        protected override void OnActivated(EventArgs e)
-        {
-            base.OnActivated(e);
-            activated(e);
-        }
-
-        protected override void OnDeactivate(EventArgs e)
-        {
-            base.OnDeactivate(e);
-            deactivated(e);
-        }
-
-        protected override void OnClosing(CancelEventArgs e)
-        {
-            base.OnClosing(e);
-            closing(e);
-        }
-
-        protected override void OnClosed(EventArgs e)
-        {
-            base.OnClosed(e);
-            closed(e);
-        }
     }
 }
\ No newline at end of file
product/client/presentation/Winforms/Views/CheckForUpdatesView.cs
@@ -12,12 +12,12 @@ namespace MoMoney.Presentation.Winforms.Views
 {
     public partial class CheckForUpdatesView : ApplicationWindow, ICheckForUpdatesView
     {
-        readonly IShell shell;
+        readonly Shell shell;
         ControlAction<EventArgs> update_button;
         ControlAction<EventArgs> dont_update_button;
         ControlAction<EventArgs> cancel_button;
 
-        public CheckForUpdatesView(IShell shell)
+        public CheckForUpdatesView(Shell shell)
         {
             InitializeComponent();
 
product/client/presentation/Winforms/Views/NavigationView.cs
@@ -10,9 +10,9 @@ namespace MoMoney.Presentation.Winforms.Views
 {
     public partial class NavigationView : ApplicationDockedWindow, INavigationView
     {
-        readonly IShell shell;
+        readonly Shell shell;
 
-        public NavigationView(IShell shell)
+        public NavigationView(Shell shell)
         {
             InitializeComponent();
             this.shell = shell;
product/client/presentation/Presentation.csproj
@@ -117,6 +117,7 @@
   <ItemGroup>
     <Compile Include="core\CachedPresenterFactory.cs" />
     <Compile Include="core\CachingViewFactory.cs" />
+    <Compile Include="core\DialogPresenter.cs" />
     <Compile Include="model\eventing\FinishedRunningCommand.cs" />
     <Compile Include="model\eventing\StartedRunningCommand.cs" />
     <Compile Include="model\menu\file\ISaveChangesCallback.cs" />
@@ -126,13 +127,14 @@
     <Compile Include="model\navigation\ITreeViewToRootNodeMapper.cs" />
     <Compile Include="model\reporting\IBindReportTo.cs" />
     <Compile Include="presenters\CommandFactory.cs" />
+    <Compile Include="presenters\SynchronizedCommandFactory.cs" />
     <Compile Include="presenters\CommandPump.cs" />
     <Compile Include="core\ApplicationController.cs" />
     <Compile Include="core\ApplicationControllerSpecs.cs" />
     <Compile Include="core\ApplicationEnvironment.cs" />
-    <Compile Include="core\ContentPresenter.cs" />
+    <Compile Include="core\TabPresenter.cs" />
     <Compile Include="core\IContentPresenter.cs" />
-    <Compile Include="core\IPresenter.cs" />
+    <Compile Include="core\Presenter.cs" />
     <Compile Include="core\PresenterRegistry.cs" />
     <Compile Include="IModule.cs" />
     <Compile Include="model\filesystem\folder.cs" />
@@ -248,6 +250,7 @@
     <Compile Include="presenters\CheckForUpdatesPresenter.cs" />
     <Compile Include="presenters\CheckForUpdatesPresenterSpecs.cs" />
     <Compile Include="presenters\ProcessQueryCommand.cs" />
+    <Compile Include="views\IDialog.cs" />
     <Compile Include="views\ISelectFileToOpenDialog.cs" />
     <Compile Include="views\ISelectFileToSaveToDialog.cs" />
     <Compile Include="views\ITaskTrayMessageView.cs" />
@@ -310,7 +313,6 @@
     <Compile Include="views\IDialogLauncher.cs" />
     <Compile Include="views\IDockedContentView.cs" />
     <Compile Include="views\IView.cs" />
-    <Compile Include="views\IWindowEvents.cs" />
     <Compile Include="views\ISaveChangesView.cs" />
     <Compile Include="winforms\views\SaveChangesView.cs">
       <SubType>Form</SubType>
@@ -375,7 +377,7 @@
     <Compile Include="views\ILogFileView.cs" />
     <Compile Include="views\INotificationIconView.cs" />
     <Compile Include="views\IRegionManager.cs" />
-    <Compile Include="views\IShell.cs" />
+    <Compile Include="views\Shell.cs" />
     <Compile Include="views\IStatusBarView.cs" />
     <Compile Include="views\IUnhandledErrorView.cs" />
     <Compile Include="winforms\views\LogFileView.cs">
product/client/service/Application/RegisterNewCompanyCommand.cs
@@ -25,7 +25,9 @@ namespace MoMoney.Service.Application
             if (is_there_a_company_registered_with(item.company_name))
                 notification.notify(create_error_message_from(item));
             else
+            {
                 factory.create().change_name_to(item.company_name);
+            }
         }
 
         bool is_there_a_company_registered_with(string company_name)
product/client/service.infrastructure/eventing/EventAggregator.cs
@@ -1,57 +1,13 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using gorilla.commons.utility;
 
 namespace MoMoney.Service.Infrastructure.Eventing
 {
-    public class EventAggregator : IEventAggregator
+    public interface EventAggregator
     {
-        readonly SynchronizationContext context;
-        readonly HashSet<object> subscribers = new HashSet<object>();
-        readonly object mutex = new object();
-
-        public EventAggregator(SynchronizationContext context)
-        {
-            this.context = context;
-        }
-
-        public void subscribe_to<Event>(IEventSubscriber<Event> subscriber) where Event : IEvent
-        {
-            subscribe(subscriber);
-        }
-
-        public void subscribe<Listener>(Listener subscriber) 
-        {
-            within_lock(() => subscribers.Add(subscriber));
-        }
-
-        public void publish<Event>(Event the_event_to_broadcast) where Event : IEvent
-        {
-            var current_subscribers = subscribers.ToList();
-            process(() => current_subscribers.call_on_each<IEventSubscriber<Event>>(x => x.notify(the_event_to_broadcast)));
-        }
-
-        public void publish<T>(Action<T> call) where T : class
-        {
-            var current_subscribers = subscribers.ToList();
-            process(() => current_subscribers.each(x => x.call_on(call)));
-        }
-
-        public void publish<Event>() where Event : IEvent, new()
-        {
-            publish(new Event());
-        }
-
-        void within_lock(Action action)
-        {
-            lock (mutex) action();
-        }
-
-        void process(Action action)
-        {
-            context.Send(x => action(), new object());
-        }
+        void subscribe_to<Event>(EventSubscriber<Event> subscriber) where Event : IEvent;
+        void subscribe<Listener>(Listener subscriber);
+        void publish<Event>(Event the_event_to_broadcast) where Event : IEvent;
+        void publish<T>(Action<T> call) where T : class;
+        void publish<Event>() where Event : IEvent, new();
     }
 }
\ No newline at end of file
product/client/service.infrastructure/eventing/EventAggregatorSpecs.cs
@@ -6,15 +6,15 @@ using Rhino.Mocks;
 
 namespace MoMoney.Service.Infrastructure.Eventing
 {
-    public abstract class behaves_like_event_aggregator : concerns_for<IEventAggregator, EventAggregator>
+    public abstract class behaves_like_event_aggregator : concerns_for<EventAggregator, SynchronizedEventAggregator>
     {
-        public override IEventAggregator create_sut()
+        public override EventAggregator create_sut()
         {
-            return new EventAggregator(new SynchronizationContext());
+            return new SynchronizedEventAggregator(new SynchronizationContext());
         }
     }
 
-    [Concern(typeof (EventAggregator))]
+    [Concern(typeof (SynchronizedEventAggregator))]
     public class when_a_event_is_raised_in_the_system : behaves_like_event_aggregator
     {
         it should_notify_all_subscribers_of_the_event = () =>
@@ -29,9 +29,9 @@ namespace MoMoney.Service.Infrastructure.Eventing
         context c = () =>
         {
             message = new TestEvent();
-            first_subscriber = an<IEventSubscriber<TestEvent>>();
-            second_subscriber = an<IEventSubscriber<TestEvent>>();
-            incorrect_subscriber = an<IEventSubscriber<AnotherEvent>>();
+            first_subscriber = an<EventSubscriber<TestEvent>>();
+            second_subscriber = an<EventSubscriber<TestEvent>>();
+            incorrect_subscriber = an<EventSubscriber<AnotherEvent>>();
         };
 
         because b = () =>
@@ -42,12 +42,12 @@ namespace MoMoney.Service.Infrastructure.Eventing
         };
 
         static TestEvent message;
-        static IEventSubscriber<TestEvent> first_subscriber;
-        static IEventSubscriber<TestEvent> second_subscriber;
-        static IEventSubscriber<AnotherEvent> incorrect_subscriber;
+        static EventSubscriber<TestEvent> first_subscriber;
+        static EventSubscriber<TestEvent> second_subscriber;
+        static EventSubscriber<AnotherEvent> incorrect_subscriber;
     }
 
-    [Concern(typeof (EventAggregator))]
+    [Concern(typeof (SynchronizedEventAggregator))]
     public class when_publishing_a_call_to_all_subscribers : behaves_like_event_aggregator
     {
         it should_make_the_call_on_each_subscriber = () => connection.was_told_to(x => x.ChangeDatabase("localhost"));
product/client/service.infrastructure/eventing/IEventSubscriber.cs → product/client/service.infrastructure/eventing/EventSubscriber.cs
@@ -1,6 +1,6 @@
 namespace MoMoney.Service.Infrastructure.Eventing
 {
-    public interface IEventSubscriber<Event> where Event : IEvent
+    public interface EventSubscriber<Event> where Event : IEvent
     {
         void notify(Event message);
     }
product/client/service.infrastructure/eventing/IEventAggregator.cs
@@ -1,13 +0,0 @@
-using System;
-
-namespace MoMoney.Service.Infrastructure.Eventing
-{
-    public interface IEventAggregator
-    {
-        void subscribe_to<Event>(IEventSubscriber<Event> subscriber) where Event : IEvent;
-        void subscribe<Listener>(Listener subscriber);
-        void publish<Event>(Event the_event_to_broadcast) where Event : IEvent;
-        void publish<T>(Action<T> call) where T : class;
-        void publish<Event>() where Event : IEvent, new();
-    }
-}
\ No newline at end of file
product/client/service.infrastructure/eventing/SynchronizedEventAggregator.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using gorilla.commons.utility;
+
+namespace MoMoney.Service.Infrastructure.Eventing
+{
+    public class SynchronizedEventAggregator : EventAggregator
+    {
+        readonly SynchronizationContext context;
+        readonly HashSet<object> subscribers = new HashSet<object>();
+        readonly object mutex = new object();
+
+        public SynchronizedEventAggregator(SynchronizationContext context)
+        {
+            this.context = context;
+        }
+
+        public void subscribe_to<Event>(EventSubscriber<Event> subscriber) where Event : IEvent
+        {
+            subscribe(subscriber);
+        }
+
+        public void subscribe<Listener>(Listener subscriber) 
+        {
+            within_lock(() => subscribers.Add(subscriber));
+        }
+
+        public void publish<Event>(Event the_event_to_broadcast) where Event : IEvent
+        {
+            var current_subscribers = subscribers.ToList();
+            process(() => current_subscribers.call_on_each<EventSubscriber<Event>>(x => x.notify(the_event_to_broadcast)));
+        }
+
+        public void publish<T>(Action<T> call) where T : class
+        {
+            var current_subscribers = subscribers.ToList();
+            process(() => current_subscribers.each(x => x.call_on(call)));
+        }
+
+        public void publish<Event>() where Event : IEvent, new()
+        {
+            publish(new Event());
+        }
+
+        void within_lock(Action action)
+        {
+            lock (mutex) action();
+        }
+
+        void process(Action action)
+        {
+            context.Send(x => action(), new object());
+        }
+    }
+}
\ No newline at end of file
product/client/service.infrastructure/threading/AsynchronousCommandProcessor.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Threading;
+using Gorilla.Commons.Infrastructure.Logging;
 using gorilla.commons.utility;
 
 namespace MoMoney.Service.Infrastructure.Threading
@@ -12,6 +13,8 @@ namespace MoMoney.Service.Infrastructure.Threading
         readonly IList<Thread> worker_threads;
         bool keep_working;
 
+        static public readonly Command Empty = new EmptyCommand();
+
         public AsynchronousCommandProcessor()
         {
             queued_commands = new Queue<Command>();
@@ -63,26 +66,48 @@ namespace MoMoney.Service.Infrastructure.Threading
 
         void run_next_command()
         {
-            Command command;
-            lock (queued_commands)
+            var command = Empty;
+            within_lock(() =>
+                        {
+                            if (queued_commands.Count == 0)
+                                manual_reset.Reset();
+                            else
+                                command = queued_commands.Dequeue();
+                        });
+            safely_invoke(() =>
+                          {
+                              this.log().debug("running command: {0}", command);
+                              command.run();
+                          });
+            reset_thread();
+        }
+
+        void safely_invoke(Action action)
+        {
+            try
             {
-                if (queued_commands.Count == 0)
-                {
-                    manual_reset.Reset();
-                    return;
-                }
-                command = queued_commands.Dequeue();
+                action();
+            }
+            catch (Exception e)
+            {
+                this.log().error(e);
             }
-            command.run();
-            reset_thread();
         }
 
         void reset_thread()
+        {
+            within_lock(() =>
+                        {
+                            if (queued_commands.Count > 0) manual_reset.Set();
+                            else manual_reset.Reset();
+                        });
+        }
+
+        void within_lock(Action action)
         {
             lock (queued_commands)
             {
-                if (queued_commands.Count > 0) manual_reset.Set();
-                else manual_reset.Reset();
+                action();
             }
         }
     }
product/client/service.infrastructure/threading/RaiseEventInterceptor.cs
@@ -9,9 +9,9 @@ namespace momoney.service.infrastructure.threading
 
     public class RaiseEventInterceptor<Event> : IRaiseEventInterceptor<Event> where Event : IEvent, new()
     {
-        readonly IEventAggregator broker;
+        readonly EventAggregator broker;
 
-        public RaiseEventInterceptor(IEventAggregator broker)
+        public RaiseEventInterceptor(EventAggregator broker)
         {
             this.broker = broker;
         }
product/client/service.infrastructure/service.infrastructure.csproj
@@ -83,11 +83,11 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="debugging\Launch.cs" />
-    <Compile Include="eventing\EventAggregator.cs" />
+    <Compile Include="eventing\SynchronizedEventAggregator.cs" />
     <Compile Include="eventing\EventAggregatorSpecs.cs" />
     <Compile Include="eventing\IEvent.cs" />
-    <Compile Include="eventing\IEventAggregator.cs" />
-    <Compile Include="eventing\IEventSubscriber.cs" />
+    <Compile Include="eventing\EventAggregator.cs" />
+    <Compile Include="eventing\EventSubscriber.cs" />
     <Compile Include="IProjectTasks.cs" />
     <Compile Include="logging\ILogFileTasks.cs" />
     <Compile Include="logging\LogFileTasks.cs" />
product/commons/infrastructure/container/Resolve.cs
@@ -5,12 +5,10 @@ namespace Gorilla.Commons.Infrastructure.Container
     static public class Resolve
     {
         static DependencyRegistry underlying_registry;
-        static bool initialized;
 
         static public void initialize_with(DependencyRegistry registry)
         {
             underlying_registry = registry;
-            initialized = registry != null;
         }
 
         static public DependencyToResolve the<DependencyToResolve>()
@@ -27,7 +25,7 @@ namespace Gorilla.Commons.Infrastructure.Container
 
         static public bool is_initialized()
         {
-            return initialized;
+            return underlying_registry != null;
         }
     }
 }
\ No newline at end of file
product/commons/utility/ChainedParameterizedCommand.cs
@@ -0,0 +1,20 @@
+namespace gorilla.commons.utility
+{
+    public class ChainedParameterizedCommand<T> : ParameterizedCommand<T>
+    {
+        ParameterizedCommand<T> left;
+        ParameterizedCommand<T> right;
+
+        public ChainedParameterizedCommand(ParameterizedCommand<T> left, ParameterizedCommand<T> right)
+        {
+            this.left = left;
+            this.right = right;
+        }
+
+        public void run(T item)
+        {
+            left.run(item);
+            right.run(item);
+        }
+    }
+}
\ No newline at end of file
product/commons/utility/CommandExtensions.cs
@@ -18,5 +18,10 @@ namespace gorilla.commons.utility
         {
             return new ChainedCommand(left, new AnonymousCommand(right));
         }
+
+        static public ParameterizedCommand<T> then<T>(this ParameterizedCommand<T> left, ParameterizedCommand<T> right)
+        {
+            return new ChainedParameterizedCommand<T>(left, right);
+        }
     }
 }
\ No newline at end of file
product/commons/utility/utility.csproj
@@ -57,6 +57,7 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ChainedParameterizedCommand.cs" />
     <Compile Include="Clock.cs" />
     <Compile Include="AnonymousCommand.cs" />
     <Compile Include="AndSpecification.cs" />
@@ -144,4 +145,4 @@
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
+</Project>
\ No newline at end of file