Commit a8a9eb2

mokhan <mokhan@ce5e1baf-6525-42e4-a1b2-857ea38da20a>
2009-03-08 06:51:33
refactored proxy builder.
git-svn-id: https://svn.xp-dev.com/svn/mokhan-mo.money@59 ce5e1baf-6525-42e4-a1b2-857ea38da20a
1 parent 37aeff5
trunk/product/MyMoney/Infrastructure/Container/Windsor/WindsorDependencyRegistry.cs
@@ -2,6 +2,8 @@ using System;
 using System.Collections.Generic;
 using Castle.Core;
 using Castle.Windsor;
+using MoMoney.Infrastructure.proxies;
+using MoMoney.Utility.Core;
 using MoMoney.Utility.Extensions;
 
 namespace MoMoney.Infrastructure.Container.Windsor
@@ -53,5 +55,12 @@ namespace MoMoney.Infrastructure.Container.Windsor
         {
             return "{0}-{1}".formatted_using(interface_type.FullName, implementation_type.FullName);
         }
+
+        public void proxy<T>(IConfiguration<IProxyBuilder<T>> configuration)
+        {
+            var builder = new ProxyBuilder<T>();
+            configuration.configure(builder);
+            singleton(builder.create_proxy_for(() => underlying_container.Resolve<T>()));
+        }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/interceptors/LazySpecs.cs
@@ -23,12 +23,12 @@ namespace MoMoney.Infrastructure.interceptors
 
     public class when_calling_a_method_with_no_arguments_on_a_lazy_loaded_proxy : behaves_like_a_lazy_loaded_object
     {
-        it should_forward_the_original_call_to_the_target = () => mocking_extensions.was_told_to(target, t => t.OneMethod());
+        it should_forward_the_original_call_to_the_target = () => target.was_told_to(t => t.OneMethod());
 
         context c = () =>
                         {
                             target = an<ITargetObject>();
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(test_container, t => t.get_a<ITargetObject>()), target).Repeat.Once();
+                            test_container.is_told_to(t => t.get_a<ITargetObject>()).it_will_return(target).Repeat.Once();
                         };
 
         because b = () =>
@@ -49,9 +49,8 @@ namespace MoMoney.Infrastructure.interceptors
                         {
                             var target = an<ITargetObject>();
 
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(target, x => x.FirstValueReturningMethod()), 10);
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(test_container, t => t.get_a<ITargetObject>()), target)
-                                .Repeat.Once();
+                            target.is_told_to(x => x.FirstValueReturningMethod()).it_will_return(10);
+                            test_container.is_told_to(t => t.get_a<ITargetObject>()).it_will_return(target) .Repeat.Once();
                         };
 
         because b = () =>
@@ -71,7 +70,7 @@ namespace MoMoney.Infrastructure.interceptors
         context c = () =>
                         {
                             var target = an<ITargetObject>();
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(test_container, t => t.get_a<ITargetObject>()), target).Repeat.Once();
+                            test_container.is_told_to(t => t.get_a<ITargetObject>()).it_will_return(target).Repeat.Once();
                         };
 
         because b = () =>
@@ -86,7 +85,7 @@ namespace MoMoney.Infrastructure.interceptors
         behaves_like_a_lazy_loaded_object
     {
         it should_forward_the_call_to_the_original_target =
-            () => mocking_extensions.was_told_to(target, x => x.ValueReturningMethodWithAnArgument(88));
+            () => target.was_told_to(x => x.ValueReturningMethodWithAnArgument(88));
 
         it should_return_the_correct_result = () => result.should_be_equal_to(99);
 
@@ -94,8 +93,8 @@ namespace MoMoney.Infrastructure.interceptors
                         {
                             target = an<ITargetObject>();
 
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(target, x => x.ValueReturningMethodWithAnArgument(88)), 99);
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(test_container, t => t.get_a<ITargetObject>()), target).Repeat.Once();
+                            target.is_told_to(x => x.ValueReturningMethodWithAnArgument(88)).it_will_return(99);
+                            test_container.is_told_to(t => t.get_a<ITargetObject>()).it_will_return(target).Repeat.Once();
                         };
 
         because b = () =>
@@ -117,7 +116,7 @@ namespace MoMoney.Infrastructure.interceptors
                             var target = an<ITargetObject>();
 
                             target.GetterAndSetterProperty = "mo";
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(test_container, t => t.get_a<ITargetObject>()), target).Repeat.Once();
+                            test_container.is_told_to(t => t.get_a<ITargetObject>()).it_will_return(target).Repeat.Once();
                         };
 
         because b = () =>
@@ -132,14 +131,12 @@ namespace MoMoney.Infrastructure.interceptors
     public class when_setting_the_value_of_a_property_on_a_proxied_object : behaves_like_a_lazy_loaded_object
     {
         it should_set_the_value_on_the_original_target =
-            () => mocking_extensions.was_told_to(target, x => x.GetterAndSetterProperty = "khan");
+            () => target.was_told_to(x => x.GetterAndSetterProperty = "khan");
 
         context c = () =>
                         {
                             target = dependency<ITargetObject>();
-
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(test_container, t => t.get_a<ITargetObject>()), target)
-                                .Repeat.Once();
+                            test_container.is_told_to(t => t.get_a<ITargetObject>()).it_will_return(target) .Repeat.Once();
                         };
 
         because b = () =>
@@ -162,8 +159,8 @@ namespace MoMoney.Infrastructure.interceptors
                         {
                             target = an<IGenericInterface<string>>();
 
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(target, x => x.ValueReturningMethodWithAnArgument("blah")), "hooray");
-                            mocking_extensions.it_will_return(mocking_extensions.is_told_to(test_container, t => t.get_a<IGenericInterface<string>>()), target).Repeat.Once();
+                            target.is_told_to(x => x.ValueReturningMethodWithAnArgument("blah")).it_will_return("hooray");
+                            test_container.is_told_to(t => t.get_a<IGenericInterface<string>>()).it_will_return(target).Repeat.Once();
                         };
 
         because b = () =>
trunk/product/MyMoney/Infrastructure/proxies/IProxyFactory.cs
@@ -1,13 +1,10 @@
 using System;
-using System.Collections.Generic;
 using Castle.Core.Interceptor;
 
 namespace MoMoney.Infrastructure.proxies
 {
     public interface IProxyFactory
     {
-        TypeToProxy create_proxy_for<TypeToProxy>(TypeToProxy implementation, IEnumerable<IInterceptor> interceptors);
-
-        TypeToProxy create_proxy_for<TypeToProxy>(Func<TypeToProxy> implementation, IEnumerable<IInterceptor> interceptors);
+        TypeToProxy create_proxy_for<TypeToProxy>(Func<TypeToProxy> implementation, params IInterceptor[] interceptors);
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/proxies/ProxyBuilder.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using Castle.Core.Interceptor;
@@ -9,6 +10,7 @@ namespace MoMoney.Infrastructure.proxies
     {
         IConstraintSelector<TypeToProxy> add_interceptor<Interceptor>() where Interceptor : IInterceptor, new();
         TypeToProxy create_proxy_for(TypeToProxy target);
+        TypeToProxy create_proxy_for(Func<TypeToProxy> target);
     }
 
     public class ProxyBuilder<TypeToProxy> : IProxyBuilder<TypeToProxy>
@@ -38,7 +40,12 @@ namespace MoMoney.Infrastructure.proxies
 
         public TypeToProxy create_proxy_for(TypeToProxy target)
         {
-            return proxy_factory.create_proxy_for(()=>target, all_interceptors_with_their_constraints());
+            return create_proxy_for(() => target);
+        }
+
+        public TypeToProxy create_proxy_for(Func<TypeToProxy> target)
+        {
+            return proxy_factory.create_proxy_for(target, all_interceptors_with_their_constraints().ToArray());
         }
 
         IEnumerable<IInterceptor> all_interceptors_with_their_constraints()
trunk/product/MyMoney/Infrastructure/proxies/ProxyFactory.cs
@@ -20,21 +20,30 @@ namespace MoMoney.Infrastructure.proxies
             this.generator = generator;
         }
 
-        public TypeToProxy create_proxy_for<TypeToProxy>(TypeToProxy implementation,
-                                                         IEnumerable<IInterceptor> interceptors)
+        public TypeToProxy create_proxy_for<TypeToProxy>(Func<TypeToProxy> implementation, params IInterceptor[] interceptors)
         {
-            return generator.CreateInterfaceProxyWithTarget<TypeToProxy>(implementation, interceptors.ToArray());
+            return create_proxy_for(lazy_load(implementation), interceptors);
         }
 
-        public TypeToProxy create_proxy_for<TypeToProxy>(Func<TypeToProxy> implementation, IEnumerable<IInterceptor> interceptors)
+        T lazy_load<T>(Func<T> implementation)
         {
-            var proxy = create_proxy_for<TypeToProxy>(() => new LazyLoadedInterceptor<TypeToProxy>(implementation));
-            return create_proxy_for(proxy, interceptors);
+            if (typeof (T).IsInterface)
+            {
+                return generator.CreateInterfaceProxyWithoutTarget<T>(new LazyLoadedInterceptor<T>(implementation));
+            }
+            return generator.CreateClassProxy<T>(new LazyLoadedInterceptor<T>(implementation));
         }
 
-        static T create_proxy_for<T>(Func<IInterceptor> interceptor)
+        TypeToProxy create_proxy_for<TypeToProxy>(TypeToProxy implementation,
+                                                  IEnumerable<IInterceptor> interceptors)
         {
-            return new ProxyGenerator().CreateInterfaceProxyWithoutTarget<T>(interceptor());
+            if (typeof (TypeToProxy).IsInterface)
+            {
+                return generator.CreateInterfaceProxyWithTarget<TypeToProxy>(implementation, interceptors.ToArray());
+            }
+            var list = interceptors.ToList();
+            list.Add(new LazyLoadedInterceptor<TypeToProxy>(() => implementation));
+            return generator.CreateClassProxy<TypeToProxy>(list.ToArray());
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/proxies/ProxyFactorySpecs.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Data;
+using Castle.Core.Interceptor;
+using jpboodhoo.bdd;
+using jpboodhoo.bdd.contexts;
+using jpboodhoo.bdd.mbunit;
+using MoMoney.Testing.MetaData;
+using MoMoney.Testing.spechelpers.contexts;
+
+namespace MoMoney.Infrastructure.proxies
+{
+    [Concern(typeof(ProxyFactory))]
+    public abstract class behaves_like_proxy_factory : concerns_for<IProxyFactory, ProxyFactory>
+    {
+        public override IProxyFactory create_sut()
+        {
+            return new ProxyFactory();
+        }
+    }
+
+    public class when_creating_a_proxy_with_a_target : behaves_like_proxy_factory
+    {
+        it should_forward_all_calls_to_the_target = () => target.was_told_to(x => x.Open());
+
+        it should_return_a_proxy_to_the_target = () =>
+                                                     {
+                                                         result.should_not_be_null();
+                                                         result.GetType().should_not_be_equal_to(target.GetType());
+                                                     };
+
+        it should_allow_the_interceptors_to_intercept_all_calls =
+            () => interceptor.recieved_call.should_be_true();
+
+        context c = () => { target = the_dependency<IDbConnection>(); };
+
+        because b = () =>
+                        {
+                            interceptor = new TestInterceptor();
+                            result = sut.create_proxy_for(() => target, interceptor);
+                            result.Open();
+                        };
+
+        static IDbConnection target;
+        static IDbConnection result;
+        static TestInterceptor interceptor;
+    }
+
+    public class when_creating_a_proxy_of_a_target_but_a_call_has_not_been_made_to_the_proxy_yet :
+        behaves_like_proxy_factory
+    {
+        it should_not_create_an_instance_of_the_target = () => TestClass.was_created.should_be_false();
+
+        context c = TestClass.reset;
+
+        because b = () => { result = sut.create_proxy_for<IDisposable>(() => new TestClass()); };
+
+        after_each_observation ae = TestClass.reset;
+
+        static IDisposable result;
+    }
+
+    public class when_creating_a_proxy_of_a_component_that_does_not_implement_an_interface : behaves_like_proxy_factory
+    {
+        it should_return_a_proxy = () => result.should_not_be_null();
+
+        because b = () => { result = sut.create_proxy_for(() => new ClassWithNoInterface()); };
+
+        after_each_observation ae = TestClass.reset;
+
+        static ClassWithNoInterface result;
+    }
+
+    public class ClassWithNoInterface
+    {
+    }
+
+    public class TestClass : IDisposable
+    {
+        public static bool was_created;
+
+        public TestClass()
+        {
+            was_created = true;
+        }
+
+        public static void reset()
+        {
+            was_created = false;
+        }
+
+        public void Dispose()
+        {
+        }
+    }
+
+
+    public class TestInterceptor : IInterceptor
+    {
+        public bool recieved_call { get; set; }
+
+        public void Intercept(IInvocation invocation)
+        {
+            recieved_call = true;
+            invocation.Proceed();
+        }
+    }
+}
\ No newline at end of file
trunk/product/MyMoney/windows.ui/wire_up_the_views_in_to_the.cs
@@ -39,6 +39,7 @@ namespace MoMoney.windows.ui
             register.transient<ICheckForUpdatesView, CheckForUpdatesView>();
             register.transient<INotificationIconView, NotificationIconView>();
             register.transient<IStatusBarView, StatusBarView>();
+            //register.proxy<IStatusBarView>(;
         }
     }
 }
\ No newline at end of file
trunk/product/MyMoney/MyMoney.csproj
@@ -237,6 +237,7 @@
     <Compile Include="Infrastructure\proxies\ProxyBuilder.cs" />
     <Compile Include="Infrastructure\proxies\ProxyBuilderSpecs.cs" />
     <Compile Include="Infrastructure\proxies\ProxyFactory.cs" />
+    <Compile Include="Infrastructure\proxies\ProxyFactorySpecs.cs" />
     <Compile Include="Infrastructure\registries\default_registry.cs" />
     <Compile Include="Infrastructure\registries\default_registry_specs.cs" />
     <Compile Include="Domain\accounting\billing\Bill.cs" />