Commit 6a443a9

mokhan <mokhan@ce5e1baf-6525-42e4-a1b2-857ea38da20a>
2009-03-24 17:00:50
fixed the broken tests.
git-svn-id: https://svn.xp-dev.com/svn/mokhan-mo.money@97 ce5e1baf-6525-42e4-a1b2-857ea38da20a
1 parent 2e5a466
trunk/product/MyMoney/DataAccess/repositories/bill_repository_specs.cs → trunk/product/MyMoney/DataAccess/repositories/BillRepositorySpecs.cs
File renamed without changes
trunk/product/MyMoney/Infrastructure/Container/Windsor/configuration/ComponentExclusionSpecification.cs
@@ -10,6 +10,7 @@ namespace MoMoney.Infrastructure.Container.Windsor.configuration
             return new NoInterfaces()
                 .or(new SubclassesForm())
                 .or(new ImplementationOfDependencyRegistry())
+                .or(new IsAnEntity())
                 .is_satisfied_by(type);
         }
     }
trunk/product/MyMoney/Infrastructure/Container/Windsor/configuration/ComponentExclusionSpecificationSpecs.cs
@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using developwithpassion.bdd.contexts;
+using MoMoney.Domain.Core;
 using MoMoney.Testing.spechelpers.contexts;
 using MoMoney.Testing.spechelpers.core;
 
@@ -31,15 +32,24 @@ namespace MoMoney.Infrastructure.Container.Windsor.configuration
         static bool result;
     }
 
-    public class when_checking_if_a_status_class_should_be_excluded : behaves_like_component_exclusion_specification
+    public class when_checking_if_a_static_class_should_be_excluded : behaves_like_component_exclusion_specification
     {
-        it should_be_excluded = () => { result.should_be_true(); };
-        
+        it should_be_excluded = () => result.should_be_true();
+
         because b = () => { result = sut.is_satisfied_by(typeof (FakeStaticClass)); };
 
         static bool result;
     }
 
+    public class when_checking_if_an_domain_entity_should_be_excluded : behaves_like_component_exclusion_specification
+    {
+        it should_be_excluded = () => result.should_be_true();
+
+        because b = () => { result = sut.is_satisfied_by(typeof (FakeEntity)); };
+
+        static bool result;
+    }
+
 
     //public class when_checking_if_a_set_of_observations_should_be_excluded : behaves_like_component_exclusion_specification
     //{
@@ -66,7 +76,15 @@ namespace MoMoney.Infrastructure.Container.Windsor.configuration
         }
     }
 
-    public static class FakeStaticClass
+    static public class FakeStaticClass
     {
     }
+
+    public class FakeEntity : IEntity
+    {
+        public Guid Id
+        {
+            get { throw new NotImplementedException(); }
+        }
+    }
 }
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/Container/Windsor/configuration/ImplementationOfDependencyRegistry.cs
@@ -6,7 +6,7 @@ namespace MoMoney.Infrastructure.Container.Windsor.configuration
     {
         public bool is_satisfied_by(Type item)
         {
-            return item.IsAssignableFrom(typeof (IDependencyRegistry));
+            return typeof (IDependencyRegistry).IsAssignableFrom(item);
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/Container/Windsor/configuration/IsAnEntity.cs
@@ -0,0 +1,14 @@
+using System;
+using MoMoney.Domain.Core;
+using MoMoney.Utility.Core;
+
+namespace MoMoney.Infrastructure.Container.Windsor.configuration
+{
+    public class IsAnEntity : ISpecification<Type>
+    {
+        public bool is_satisfied_by(Type item)
+        {
+            return typeof (IEntity).IsAssignableFrom(item);
+        }
+    }
+}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/Container/Windsor/WindsorDependencyRegistrySpecs.cs
@@ -8,24 +8,24 @@ using MoMoney.Testing.spechelpers.core;
 namespace MoMoney.Infrastructure.Container.Windsor
 {
     [Concern(typeof (WindsorDependencyRegistry))]
-    [run_in_real_container]
-    public class when_registering_a_singleton_component_with_the_windsor_container : concerns_for<IDependencyRegistry>
+    internal class behaves_like_windsor_dependency_registry :
+        concerns_for<IDependencyRegistry, WindsorDependencyRegistry>
+    {
+    }
+
+    internal class when_registering_a_singleton_component_with_the_windsor_container :
+        behaves_like_windsor_dependency_registry
     {
         it should_return_the_same_instance_each_time_its_resolved =
             () => result.should_be_the_same_instance_as(sut.get_a<IBird>());
 
         it should_not_return_null = () => result.should_not_be_null();
 
-        public override IDependencyRegistry create_sut()
-        {
-            return resolve.dependency_for<IDependencyRegistry>();
-        }
-
         context c = () =>
                         {
                             var container = the_dependency<IWindsorContainer>();
                             var bird = new BlueBird();
-                            container.is_told_to(x => x.Resolve<IBird>()).it_will_return(bird);
+                            container.is_told_to(x => x.Resolve<IBird>()).it_will_return(bird).Repeat.Any();
                         };
 
         because b = () => { result = sut.get_a<IBird>(); };
trunk/product/MyMoney/Infrastructure/Threading/Juval/Synchronizer.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Security.Permissions;
+using System.Threading;
+
+namespace MoMoney.Infrastructure.Threading.Juval
+{
+    [SecurityPermission(SecurityAction.Demand, ControlThread = true)]
+    public class Synchronizer : ISynchronizeInvoke, IDisposable
+    {
+        readonly WorkerThread worker_thread;
+
+        public Synchronizer()
+        {
+            worker_thread = new WorkerThread(this);
+        }
+
+        public bool InvokeRequired
+        {
+            get { return ReferenceEquals(Thread.CurrentThread, worker_thread); }
+        }
+
+        public IAsyncResult BeginInvoke(Delegate method, object[] args)
+        {
+            var result = new WorkItem(null, method, args);
+            worker_thread.QueueWorkItem(result);
+            return result;
+        }
+
+        public object EndInvoke(IAsyncResult result)
+        {
+            result.AsyncWaitHandle.WaitOne();
+            return ((WorkItem) result).MethodReturnedValue;
+        }
+
+        public object Invoke(Delegate method, object[] args)
+        {
+            return EndInvoke(BeginInvoke(method, args));
+        }
+
+        ~Synchronizer()
+        {
+        }
+
+        public void Dispose()
+        {
+            worker_thread.Kill();
+        }
+
+        class WorkerThread
+        {
+            Thread thread;
+            bool end_loop;
+            readonly Mutex end_loop_mutex;
+            readonly AutoResetEvent item_added;
+            Synchronizer synchronizer;
+            readonly Queue work_item_queue;
+
+            internal WorkerThread(Synchronizer synchronizer)
+            {
+                this.synchronizer = synchronizer;
+                end_loop = false;
+                thread = null;
+                end_loop_mutex = new Mutex();
+                item_added = new AutoResetEvent(false);
+                work_item_queue = new Queue();
+                CreateThread(true);
+            }
+
+            internal void QueueWorkItem(WorkItem workItem)
+            {
+                lock (work_item_queue.SyncRoot)
+                {
+                    work_item_queue.Enqueue(workItem);
+                    item_added.Set();
+                }
+            }
+
+            bool EndLoop
+            {
+                set
+                {
+                    end_loop_mutex.WaitOne();
+                    end_loop = value;
+                    end_loop_mutex.ReleaseMutex();
+                }
+                get
+                {
+                    var result = false;
+                    end_loop_mutex.WaitOne();
+                    result = end_loop;
+                    end_loop_mutex.ReleaseMutex();
+                    return result;
+                }
+            }
+
+            Thread CreateThread(bool autoStart)
+            {
+                if (thread != null)
+                {
+                    Debug.Assert(false);
+                    return thread;
+                }
+                thread = new Thread(Run) {Name = "Synchronizer Worker Thread"};
+                if (autoStart)
+                {
+                    thread.Start();
+                }
+                return thread;
+            }
+
+            void Start()
+            {
+                Debug.Assert(thread != null);
+                Debug.Assert(thread.IsAlive == false);
+                thread.Start();
+            }
+
+            bool QueueEmpty
+            {
+                get
+                {
+                    lock (work_item_queue.SyncRoot)
+                    {
+                        if (work_item_queue.Count > 0)
+                        {
+                            return false;
+                        }
+                        return true;
+                    }
+                }
+            }
+
+            WorkItem GetNext()
+            {
+                if (QueueEmpty)
+                {
+                    return null;
+                }
+                lock (work_item_queue.SyncRoot)
+                {
+                    return (WorkItem) work_item_queue.Dequeue();
+                }
+            }
+
+            void Run()
+            {
+                while (EndLoop == false)
+                {
+                    while (QueueEmpty == false)
+                    {
+                        if (EndLoop)
+                        {
+                            return;
+                        }
+                        var workItem = GetNext();
+                        workItem.CallBack();
+                    }
+                    item_added.WaitOne();
+                }
+            }
+
+            public void Kill()
+            {
+                //Kill is called on client thread - must use cached thread object
+                Debug.Assert(thread != null);
+                if (thread.IsAlive == false)
+                {
+                    return;
+                }
+                EndLoop = true;
+                item_added.Set();
+
+                //Wait for thread to die
+                thread.Join();
+                if (end_loop_mutex != null)
+                {
+                    end_loop_mutex.Close();
+                }
+                if (item_added != null)
+                {
+                    item_added.Close();
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/Threading/Juval/WorkItem.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Threading;
+
+namespace MoMoney.Infrastructure.Threading.Juval
+{
+    [Serializable]
+    internal class WorkItem : IAsyncResult
+    {
+        readonly object[] m_Args;
+        readonly object m_AsyncState;
+        bool m_Completed;
+        readonly Delegate m_Method;
+        readonly ManualResetEvent m_Event;
+        object m_MethodReturnedValue;
+
+        internal WorkItem(object AsyncState, Delegate method, object[] args)
+        {
+            m_AsyncState = AsyncState;
+            m_Method = method;
+            m_Args = args;
+            m_Event = new ManualResetEvent(false);
+            m_Completed = false;
+        }
+
+        //IAsyncResult properties 
+        object IAsyncResult.AsyncState
+        {
+            get { return m_AsyncState; }
+        }
+
+        WaitHandle IAsyncResult.AsyncWaitHandle
+        {
+            get { return m_Event; }
+        }
+
+        bool IAsyncResult.CompletedSynchronously
+        {
+            get { return false; }
+        }
+
+        bool IAsyncResult.IsCompleted
+        {
+            get { return Completed; }
+        }
+
+        bool Completed
+        {
+            get
+            {
+                lock (this)
+                {
+                    return m_Completed;
+                }
+            }
+            set
+            {
+                lock (this)
+                {
+                    m_Completed = value;
+                }
+            }
+        }
+
+        //This method is called on the worker thread to execute the method
+        internal void CallBack()
+        {
+            MethodReturnedValue = m_Method.DynamicInvoke(m_Args);
+            //Method is done. Signal the world
+            m_Event.Set();
+            Completed = true;
+        }
+
+        internal object MethodReturnedValue
+        {
+            get
+            {
+                object methodReturnedValue;
+                lock (this)
+                {
+                    methodReturnedValue = m_MethodReturnedValue;
+                }
+                return methodReturnedValue;
+            }
+            set
+            {
+                lock (this)
+                {
+                    m_MethodReturnedValue = value;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/transactions/UnitOfWork.cs
@@ -1,5 +1,7 @@
+using System;
 using MoMoney.Domain.Core;
 using MoMoney.Infrastructure.Container;
+using MoMoney.Infrastructure.Logging;
 
 namespace MoMoney.Infrastructure.transactions
 {
@@ -7,11 +9,19 @@ namespace MoMoney.Infrastructure.transactions
     {
         static public IUnitOfWork<T> For<T>() where T : IEntity
         {
+            IUnitOfWork<T> unit_of_work = null;
             if (resolve.is_initialized())
             {
-                return resolve.dependency_for<IUnitOfWorkRegistry>().start_unit_of_work_for<T>();
+                try
+                {
+                    unit_of_work = resolve.dependency_for<IUnitOfWorkRegistry>().start_unit_of_work_for<T>();
+                }
+                catch (Exception exception)
+                {
+                    Log.For(typeof (UnitOfWork)).error(exception);
+                }
             }
-            return new NullUnitOfWork<T>();
+            return unit_of_work ?? new NullUnitOfWork<T>();
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/MyMoney.csproj
@@ -178,7 +178,7 @@
     <Compile Include="DataAccess\db40\Session.cs" />
     <Compile Include="DataAccess\db40\spiking\db40_spike_specs.cs" />
     <Compile Include="DataAccess\repositories\BillRepository.cs" />
-    <Compile Include="DataAccess\repositories\bill_repository_specs.cs" />
+    <Compile Include="DataAccess\repositories\BillRepositorySpecs.cs" />
     <Compile Include="DataAccess\repositories\CompanyRepository.cs" />
     <Compile Include="Domain\accounting\billing\IEmployee.cs" />
     <Compile Include="Domain\accounting\financial_growth\income.cs" />
@@ -226,6 +226,7 @@
     <Compile Include="Infrastructure\Container\Windsor\configuration\ConfigureComponentLifestyle.cs" />
     <Compile Include="Infrastructure\Container\Windsor\configuration\IComponentExclusionSpecification.cs" />
     <Compile Include="Infrastructure\Container\Windsor\configuration\ImplementationOfDependencyRegistry.cs" />
+    <Compile Include="Infrastructure\Container\Windsor\configuration\IsAnEntity.cs" />
     <Compile Include="Infrastructure\Container\Windsor\configuration\LogComponent.cs" />
     <Compile Include="Infrastructure\Container\Windsor\configuration\NoInterfaces.cs" />
     <Compile Include="Infrastructure\Container\Windsor\configuration\RegisterComponentContract.cs" />
@@ -282,6 +283,8 @@
     <Compile Include="Infrastructure\Threading\BackgroundThread.cs">
     </Compile>
     <Compile Include="Infrastructure\Threading\IntervalTimer.cs" />
+    <Compile Include="Infrastructure\Threading\Juval\Synchronizer.cs" />
+    <Compile Include="Infrastructure\Threading\Juval\WorkItem.cs" />
     <Compile Include="Infrastructure\Threading\TimerFactory.cs" />
     <Compile Include="Infrastructure\Threading\WorkerThread.cs">
       <SubType>Component</SubType>