PageRenderTime 23ms CodeModel.GetById 17ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/LinFu.AOP/Extensions/MethodCallInterceptionExtensions.cs

http://github.com/philiplaureano/LinFu
C# | 170 lines | 85 code | 14 blank | 71 comment | 1 complexity | aa3354bf4b463366d14c62fbaaff8296 MD5 | raw file
  1using System;
  2using System.Linq;
  3using LinFu.AOP.Cecil.Interfaces;
  4using LinFu.AOP.Interfaces;
  5using Mono.Cecil;
  6
  7namespace LinFu.AOP.Cecil.Extensions
  8{
  9    /// <summary>
 10    ///     Represents an extension class that adds method call interception support to the Mono.Cecil object model.
 11    /// </summary>
 12    public static class MethodCallInterceptionExtensions
 13    {
 14        /// <summary>
 15        ///     Modifies the current <paramref name="target" /> to support third-party method call interception for all method
 16        ///     calls made inside the target.
 17        /// </summary>
 18        /// <param name="target">The target object.</param>
 19        public static void InterceptAllMethodCalls(this AssemblyDefinition target)
 20        {
 21            target.InterceptMethodCalls(GetDefaultTypeFilter());
 22        }
 23
 24        /// <summary>
 25        ///     Modifies the current <paramref name="target" /> to support third-party method call interception for all method
 26        ///     calls made inside the target.
 27        /// </summary>
 28        /// <param name="target">The target object.</param>
 29        public static void InterceptAllMethodCalls(this TypeDefinition target)
 30        {
 31            var hostMethodFilter = GetHostMethodFilter();
 32            Func<MethodReference, bool> methodCallFilter = m => true;
 33
 34            InterceptMethodCalls(target, GetDefaultTypeFilter(), hostMethodFilter, methodCallFilter);
 35        }
 36
 37        /// <summary>
 38        ///     Modifies the current <paramref name="target" /> to support third-party method call interception for all method
 39        ///     calls made inside the target.
 40        /// </summary>
 41        /// <param name="target">The target object.</param>
 42        /// <param name="typeFilter">The type filter that determines which types will be modified for interception.</param>
 43        public static void InterceptMethodCalls(this AssemblyDefinition target,
 44            Func<TypeReference, bool> typeFilter)
 45        {
 46            var hostMethodFilter = GetHostMethodFilter();
 47            Func<MethodReference, bool> methodCallFilter = m => true;
 48
 49            InterceptMethodCalls(target, typeFilter, hostMethodFilter, methodCallFilter);
 50        }
 51
 52        /// <summary>
 53        ///     Modifies the current <paramref name="target" /> to support third-party method call interception for all method
 54        ///     calls made inside the target.
 55        /// </summary>
 56        /// <param name="target">The target object.</param>
 57        /// <param name="typeFilter">The type filter that determines the types that will be modified.</param>
 58        public static void InterceptMethodCalls(this TypeDefinition target, Func<TypeReference, bool> typeFilter)
 59        {
 60            var hostMethodFilter = GetHostMethodFilter();
 61            Func<MethodReference, bool> methodCallFilter = m => true;
 62
 63            InterceptMethodCalls(target, typeFilter, hostMethodFilter, methodCallFilter);
 64        }
 65
 66        /// <summary>
 67        ///     Modifies the current <paramref name="target" /> to support third-party method call interception for all method
 68        ///     calls made inside the target.
 69        /// </summary>
 70        /// <param name="target">The target object.</param>
 71        /// <param name="methodCallFilter">
 72        ///     The <see cref="IMethodCallFilter" /> instance that determines the method calls that will
 73        ///     be intercepted.
 74        /// </param>
 75        /// <param name="hostMethodFilter">
 76        ///     The <see cref="IMethodFilter" /> instance that determines the host method calls that
 77        ///     will be modified
 78        /// </param>
 79        public static void InterceptMethodCalls(this TypeDefinition target, IMethodCallFilter methodCallFilter,
 80            IMethodFilter hostMethodFilter)
 81        {
 82            var rewriter = new InterceptMethodCalls(methodCallFilter);
 83            target.Accept(new ImplementModifiableType(GetDefaultTypeFilter()));
 84            target.WeaveWith(rewriter);
 85        }
 86
 87        /// <summary>
 88        ///     Modifies the current <paramref name="target" /> to support third-party method call interception for all method
 89        ///     calls made inside the target.
 90        /// </summary>
 91        /// <param name="target">The target object.</param>
 92        /// <param name="methodCallFilter">
 93        ///     The <see cref="IMethodCallFilter" /> instance that determines the method calls that will
 94        ///     be intercepted.
 95        /// </param>
 96        /// <param name="hostMethodFilter">
 97        ///     The <see cref="IMethodFilter" /> instance that determines the host method calls that
 98        ///     will be modified
 99        /// </param>
100        public static void InterceptMethodCalls(this AssemblyDefinition target,
101            IMethodCallFilter methodCallFilter,
102            IMethodFilter hostMethodFilter)
103        {
104            var module = target.MainModule;
105            var methods = module.Types.Where(t => GetDefaultTypeFilter()(t)).SelectMany(t => t.Methods)
106                .Where(hostMethodFilter.ShouldWeave).ToArray();
107
108            var rewriter = new InterceptMethodCalls(methodCallFilter);
109            target.Accept(new ImplementModifiableType(GetDefaultTypeFilter()));
110            target.WeaveWith(rewriter);
111        }
112
113        /// <summary>
114        ///     Modifies the current <paramref name="target" /> to support third-party method call interception.
115        /// </summary>
116        /// <param name="target">The target object.</param>
117        /// <param name="typeFilter">The filter that will determine the target types that will be modified.</param>
118        /// <param name="hostMethodFilter">The filter that will determine the methods that will be modified on the target type.</param>
119        /// <param name="methodCallFilter">
120        ///     The filter that will determine which third-party methods will be intercepted on the
121        ///     target type.
122        /// </param>
123        public static void InterceptMethodCalls(this AssemblyDefinition target,
124            Func<TypeReference, bool> typeFilter,
125            Func<MethodReference, bool> hostMethodFilter,
126            Func<MethodReference, bool> methodCallFilter)
127        {
128            var rewriter = new InterceptMethodCalls(hostMethodFilter, methodCallFilter);
129            target.Accept(new ImplementModifiableType(typeFilter));
130            target.WeaveWith(rewriter);
131        }
132
133        /// <summary>
134        ///     Modifies the current <paramref name="target" /> to support third-party method call interception.
135        /// </summary>
136        /// <param name="target">The target object.</param>
137        /// <param name="typeFilter">The filter that will determine the target types that will be modified.</param>
138        /// <param name="hostMethodFilter">The filter that will determine the methods that will be modified on the target type.</param>
139        /// <param name="methodCallFilter">
140        ///     The filter that will determine which third-party methods will be intercepted on the
141        ///     target type.
142        /// </param>
143        public static void InterceptMethodCalls(this TypeDefinition target, Func<TypeReference, bool> typeFilter,
144            Func<MethodReference, bool> hostMethodFilter,
145            Func<MethodReference, bool> methodCallFilter)
146        {
147            var rewriter = new InterceptMethodCalls(hostMethodFilter, methodCallFilter);
148            target.Accept(new ImplementModifiableType(typeFilter));
149            target.WeaveWith(rewriter);
150        }
151
152        private static Func<TypeReference, bool> GetDefaultTypeFilter()
153        {
154            return type =>
155            {
156                var actualType1 = type.Resolve();
157                return !actualType1.IsValueType && !actualType1.IsInterface;
158            };
159        }
160
161        private static Func<MethodReference, bool> GetHostMethodFilter()
162        {
163            return method =>
164            {
165                var actualMethod = method.Resolve();
166                return actualMethod.HasBody;
167            };
168        }
169    }
170}