PageRenderTime 162ms CodeModel.GetById 80ms app.highlight 3ms RepoModel.GetById 78ms app.codeStats 0ms

/src/LinFu.AOP.Interfaces/BaseMethodReplacementProvider.cs

http://github.com/philiplaureano/LinFu
C# | 81 lines | 35 code | 10 blank | 36 comment | 3 complexity | c4538626875f54cf9ea85bc029ec8fbd MD5 | raw file
 1namespace LinFu.AOP.Interfaces
 2{
 3    /// <summary>
 4    ///     Represents the boilerplate implementation for a <see cref="IMethodReplacementProvider" /> instance.
 5    /// </summary>
 6    public abstract class BaseMethodReplacementProvider : IMethodReplacementProvider, IAroundInvoke
 7    {
 8        private readonly ICallCounter _counter = new MultiThreadedCallCounter();
 9
10        /// <summary>
11        /// The hook method that is called after each intercepted method is called.
12        /// </summary>
13        /// <param name="context">The context of the method call that is being intercepted.</param>
14        /// <param name="returnValue">The value returned from the method call</param>
15        public void AfterInvoke(IInvocationInfo context, object returnValue)
16        {
17            _counter.Decrement(context);
18        }
19
20        /// <summary>
21        /// The hook method that is called after each intercepted method is called.
22        /// </summary>
23        /// <param name="context">The context of the method call that is being intercepted.</param>
24        public void BeforeInvoke(IInvocationInfo context)
25        {
26            _counter.Increment(context);
27        }
28
29        /// <summary>
30        ///     Determines whether or not the current method implementation can be replaced.
31        /// </summary>
32        /// <param name="host">The target instance of the method call.</param>
33        /// <param name="context">The <see cref="IInvocationInfo" /> that describes the context of the method call.</param>
34        /// <returns><c>true</c> if the method can be intercepted; otherwise, it will return <c>false</c>.</returns>
35        public bool CanReplace(object host, IInvocationInfo context)
36        {
37            var pendingCalls = _counter.GetPendingCalls(context);
38
39            if (pendingCalls > 0)
40                return false;
41
42            return ShouldReplace(host, context);
43        }
44
45        /// <summary>
46        ///     Obtains the <see cref="IInterceptor" /> instance that will be used to replace the current method call.
47        /// </summary>
48        /// <param name="host">The target instance of the method call.</param>
49        /// <param name="context">The <see cref="IInvocationInfo" /> that describes the context of the method call.</param>
50        /// <returns>The interceptor that will intercept the method call itself.</returns>
51        public IInterceptor GetMethodReplacement(object host, IInvocationInfo context)
52        {
53            var pendingCalls = _counter.GetPendingCalls(context);
54
55            if (pendingCalls > 0)
56                return null;
57
58            var methodReplacement = GetReplacement(host, context);
59            return new CountingInterceptor(_counter, methodReplacement);
60        }
61
62        /// <summary>
63        /// Determines whether or not a given method should be intercepted or replaced.
64        /// </summary>
65        /// <param name="host">The actual object or target instance that hosts the method</param>
66        /// <param name="context">The context that describes the method call</param>
67        /// <returns></returns>
68        protected virtual bool ShouldReplace(object host, IInvocationInfo context)
69        {
70            return _counter.GetPendingCalls(context) == 0;
71        }
72
73        /// <summary>
74        ///     Obtains the <see cref="IInterceptor" /> instance that will be used to replace the current method call.
75        /// </summary>
76        /// <param name="host">The target instance of the method call.</param>
77        /// <param name="context">The <see cref="IInvocationInfo" /> that describes the context of the method call.</param>
78        /// <returns>The interceptor that will intercept the method call itself.</returns>
79        protected abstract IInterceptor GetReplacement(object host, IInvocationInfo context);
80    }
81}