Commit 19e4419
Changed files (11)
trunk
product
MyMoney
boot
container
Infrastructure
Utility
Extensions
trunk/product/MyMoney/boot/container/registration/wire_up_the_essential_services_into_the.cs
@@ -1,6 +1,8 @@
+using System.Threading;
using MoMoney.Infrastructure.Container.Windsor;
using MoMoney.Infrastructure.Logging;
using MoMoney.Infrastructure.Logging.Log4NetLogging;
+using MoMoney.Infrastructure.Threading;
using MoMoney.Utility.Core;
namespace MoMoney.boot.container.registration
@@ -18,6 +20,7 @@ namespace MoMoney.boot.container.registration
{
registration.singleton<IDependencyRegistration>(registration);
registration.singleton<ILogFactory, Log4NetLogFactory>();
+ registration.singleton<ISynchronizationContext>(new SynchronizedContext(SynchronizationContext.Current));
}
}
}
\ No newline at end of file
trunk/product/MyMoney/boot/container/registration/wire_up_the_views_in_to_the.cs
@@ -2,6 +2,7 @@ using System.ComponentModel;
using MoMoney.Infrastructure.Container.Windsor;
using MoMoney.Infrastructure.interceptors;
using MoMoney.Infrastructure.proxies;
+using MoMoney.Infrastructure.Threading;
using MoMoney.Presentation.Views;
using MoMoney.Presentation.Views.billing;
using MoMoney.Presentation.Views.dialogs;
@@ -28,6 +29,7 @@ namespace MoMoney.boot.container.registration
{
var shell = new ApplicationShell();
register.singleton<IShell>(shell);
+ //register.proxy<IShell>(new SynchronizedConfiguration<IShell>(), () => shell);
register.singleton(shell);
//register.proxy(new SynchronizedViewProxyConfiguration<IShell>(), () => new ApplicationShell());
register.transient<IAboutApplicationView, AboutTheApplicationView>();
@@ -56,4 +58,12 @@ namespace MoMoney.boot.container.registration
item.add_interceptor<SynchronizedInterceptor<T>>();
}
}
+
+ internal class SynchronizedConfiguration<T> : IConfiguration<IProxyBuilder<T>>
+ {
+ public void configure(IProxyBuilder<T> item)
+ {
+ item.add_interceptor<IThreadSafeInterceptor>( new ThreadSafeInterceptor(Lazy.load<ISynchronizationContextFactory>())).InterceptAll();
+ }
+ }
}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/proxies/Interceptors/MethodCallTracker.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using Castle.Core.Interceptor;
+using MoMoney.Infrastructure.Extensions;
+using MoMoney.Utility.Extensions;
namespace MoMoney.Infrastructure.proxies.Interceptors
{
@@ -21,6 +23,7 @@ namespace MoMoney.Infrastructure.proxies.Interceptors
public void Intercept(IInvocation invocation)
{
+ this.log().debug("recording: {0}", invocation.Method);
set_return_value_for(invocation);
if (the_name_of_each_method_to_intercept.Contains(invocation.Method.Name))
{
@@ -38,12 +41,12 @@ namespace MoMoney.Infrastructure.proxies.Interceptors
{
var return_type = invocation.Method.ReturnType;
if (return_type == typeof (void)) return;
- invocation.ReturnValue = get_default_value_for(return_type);
+ invocation.ReturnValue = return_type.default_value();
}
- static object get_default_value_for(Type return_type)
- {
- return (return_type.IsValueType ? Activator.CreateInstance(return_type) : null);
- }
+ //static object get_default_value_for(Type return_type)
+ //{
+ // return (return_type.IsValueType ? Activator.CreateInstance(return_type) : null);
+ //}
}
}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/proxies/IConstraintSelector.cs
@@ -3,5 +3,6 @@ namespace MoMoney.Infrastructure.proxies
public interface IConstraintSelector<TypeToPutConstraintOn>
{
TypeToPutConstraintOn InterceptOn { get; }
+ void InterceptAll();
}
}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/proxies/IInterceptorConstraint.cs
@@ -1,5 +1,9 @@
using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using MoMoney.Infrastructure.Extensions;
using MoMoney.Infrastructure.proxies.Interceptors;
+using MoMoney.Utility.Extensions;
namespace MoMoney.Infrastructure.proxies
{
@@ -10,7 +14,7 @@ namespace MoMoney.Infrastructure.proxies
public class InterceptorConstraint<TypeToPutConstraintOn> : IInterceptorConstraint<TypeToPutConstraintOn>
{
- private readonly IMethodCallTracker<TypeToPutConstraintOn> call_tracker;
+ readonly IMethodCallTracker<TypeToPutConstraintOn> call_tracker;
public InterceptorConstraint(IMethodCallTracker<TypeToPutConstraintOn> call_tracker)
{
@@ -22,6 +26,24 @@ namespace MoMoney.Infrastructure.proxies
get { return call_tracker.target; }
}
+ public void InterceptAll()
+ {
+ var methods = typeof (TypeToPutConstraintOn).GetMethods(BindingFlags.Public | BindingFlags.Instance);
+ foreach (var method in methods)
+ {
+ method.Invoke(InterceptOn, get_stub_parameters_for(method).ToArray());
+ }
+ }
+
+ IEnumerable<object> get_stub_parameters_for(MethodInfo method)
+ {
+ foreach (var parameter in method.GetParameters())
+ {
+ this.log().debug("method: {0}, param: {1}", method, parameter);
+ yield return parameter.ParameterType.default_value();
+ }
+ }
+
public IEnumerable<string> methods_to_intercept()
{
return call_tracker.methods_to_intercept();
trunk/product/MyMoney/Infrastructure/proxies/ProxyBuilderSpecs.cs
@@ -85,6 +85,37 @@ namespace MoMoney.Infrastructure.proxies
static IAnInterface an_implementation;
}
+ public class when_proxying_all_calls_on_a_target : behaves_like_proxy_builder
+ {
+ it should_intercept_each_call =
+ () =>
+ {
+ SomeInterceptor.MethodsCalled.Count().should_be_equal_to(2);
+ SomeInterceptor.MethodsCalled.First().Name.should_be_equal_to("OneMethod");
+ SomeInterceptor.MethodsCalled.Skip(1).First().Name.should_be_equal_to( "SecondMethod");
+ };
+
+ context c = () => { an_implementation = an<IAnInterface>(); };
+
+ because b = () =>
+ {
+ var constraint = sut.add_interceptor<SomeInterceptor>();
+ constraint.InterceptAll();
+
+ var proxy = sut.create_proxy_for(() => an_implementation);
+ proxy.OneMethod();
+ proxy.SecondMethod();
+ };
+
+ after_each_observation ae = () =>
+ {
+ SomeInterceptor.Cleanup();
+ AnotherInterceptor.Cleanup();
+ };
+
+ static IAnInterface an_implementation;
+ }
+
public interface IAnInterface
{
string GetterAndSetterProperty { get; set; }
@@ -96,8 +127,8 @@ namespace MoMoney.Infrastructure.proxies
public class SomeInterceptor : IInterceptor
{
- public static bool WasCalled;
- public static IList<MethodInfo> MethodsCalled;
+ static public bool WasCalled;
+ static public IList<MethodInfo> MethodsCalled;
static SomeInterceptor()
{
@@ -111,7 +142,7 @@ namespace MoMoney.Infrastructure.proxies
invocation.Proceed();
}
- public static void Cleanup()
+ static public void Cleanup()
{
WasCalled = false;
MethodsCalled.Clear();
@@ -120,8 +151,8 @@ namespace MoMoney.Infrastructure.proxies
public class AnotherInterceptor : IInterceptor
{
- public static bool WasCalled;
- public static IList<MethodInfo> MethodsCalled;
+ static public bool WasCalled;
+ static public IList<MethodInfo> MethodsCalled;
static AnotherInterceptor()
{
@@ -135,7 +166,7 @@ namespace MoMoney.Infrastructure.proxies
invocation.Proceed();
}
- public static void Cleanup()
+ static public void Cleanup()
{
WasCalled = false;
MethodsCalled.Clear();
trunk/product/MyMoney/Infrastructure/Threading/SynchronizationContext.cs
@@ -0,0 +1,24 @@
+using System.Threading;
+using MoMoney.Utility.Core;
+
+namespace MoMoney.Infrastructure.Threading
+{
+ public interface ISynchronizationContext : IParameterizedCommand<ICommand>
+ {
+ }
+
+ public class SynchronizedContext : ISynchronizationContext
+ {
+ readonly SynchronizationContext context;
+
+ public SynchronizedContext(SynchronizationContext context)
+ {
+ this.context = context;
+ }
+
+ public void run(ICommand item)
+ {
+ context.Post(x => item.run(), null);
+ }
+ }
+}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/Threading/SynchronizationContextFactory.cs
@@ -0,0 +1,23 @@
+using MoMoney.Utility.Core;
+
+namespace MoMoney.Infrastructure.Threading
+{
+ public interface ISynchronizationContextFactory : IFactory<ISynchronizationContext>
+ {
+ }
+
+ public class SynchronizationContextFactory : ISynchronizationContextFactory
+ {
+ readonly ISynchronizationContext context;
+
+ public SynchronizationContextFactory(ISynchronizationContext context)
+ {
+ this.context = context;
+ }
+
+ public ISynchronizationContext create()
+ {
+ return context;
+ }
+ }
+}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/Threading/ThreadSafeInterceptor.cs
@@ -0,0 +1,24 @@
+using Castle.Core.Interceptor;
+using MoMoney.Utility.Core;
+
+namespace MoMoney.Infrastructure.Threading
+{
+ public interface IThreadSafeInterceptor : IInterceptor
+ {
+ }
+
+ public class ThreadSafeInterceptor : IThreadSafeInterceptor
+ {
+ readonly ISynchronizationContextFactory factory;
+
+ public ThreadSafeInterceptor(ISynchronizationContextFactory factory)
+ {
+ this.factory = factory;
+ }
+
+ public void Intercept(IInvocation invocation)
+ {
+ factory.create().run(new ActionCommand(invocation.Proceed));
+ }
+ }
+}
\ No newline at end of file
trunk/product/MyMoney/Utility/Extensions/TypeExtensions.cs
@@ -2,22 +2,27 @@ using System;
namespace MoMoney.Utility.Extensions
{
- public static class TypeExtensions
+ static public class TypeExtensions
{
- public static Type last_interface(this Type type)
+ static public Type last_interface(this Type type)
{
return type.GetInterfaces()[type.GetInterfaces().Length - 1];
}
- public static Type first_interface(this Type type)
+ static public Type first_interface(this Type type)
{
return type.GetInterfaces()[0];
}
- public static bool is_a_generic_type(this Type type)
+ static public bool is_a_generic_type(this Type type)
{
//return type.IsGenericType;
return type.IsGenericTypeDefinition;
}
+
+ static public object default_value(this Type type)
+ {
+ return (type.IsValueType ? Activator.CreateInstance(type) : null);
+ }
}
}
\ No newline at end of file
trunk/product/MyMoney/MyMoney.csproj
@@ -282,6 +282,9 @@
<Compile Include="Infrastructure\Threading\IntervalTimer.cs" />
<Compile Include="Infrastructure\Threading\Juval\Synchronizer.cs" />
<Compile Include="Infrastructure\Threading\Juval\WorkItem.cs" />
+ <Compile Include="Infrastructure\Threading\SynchronizationContext.cs" />
+ <Compile Include="Infrastructure\Threading\SynchronizationContextFactory.cs" />
+ <Compile Include="Infrastructure\Threading\ThreadSafeInterceptor.cs" />
<Compile Include="Infrastructure\Threading\TimerFactory.cs" />
<Compile Include="Infrastructure\Threading\WorkerThread.cs">
<SubType>Component</SubType>