PageRenderTime 44ms CodeModel.GetById 37ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/LinFu.AOP/MethodRewriter.cs

http://github.com/philiplaureano/LinFu
C# | 97 lines | 46 code | 16 blank | 35 comment | 4 complexity | a2233e848c033e3f53d75dc2c8059f4c MD5 | raw file
 1using System.Collections.Generic;
 2using LinFu.AOP.Cecil.Interfaces;
 3using Mono.Cecil;
 4using Mono.Cecil.Cil;
 5
 6namespace LinFu.AOP.Cecil
 7{
 8    /// <summary>
 9    ///     Provides the basic functionality for the <see cref="IMethodRewriter" /> interface.
10    /// </summary>
11    public abstract class MethodRewriter : IMethodRewriter
12    {
13        private readonly HashSet<TypeDefinition> _modifiedTypes = new HashSet<TypeDefinition>();
14
15
16        /// <summary>
17        ///     Rewrites a target method using the given ILProcessor.
18        /// </summary>
19        /// <param name="method">The target method.</param>
20        /// <param name="IL">The ILProcessor that will be used to rewrite the target method.</param>
21        /// <param name="oldInstructions">The original instructions from the target method body.</param>
22        public void Rewrite(MethodDefinition method, ILProcessor IL, IEnumerable<Instruction> oldInstructions)
23        {
24            var declaringType = method.DeclaringType;
25            var module = declaringType.Module;
26
27            // Interfaces and Enums cannot be modified
28            if (declaringType.IsInterface || declaringType.IsEnum)
29                return;
30
31            ImportReferences(module);
32
33            AddLocals(method);
34
35            if (!_modifiedTypes.Contains(declaringType))
36            {
37                AddAdditionalMembers(declaringType);
38                _modifiedTypes.Add(declaringType);
39            }
40
41            var newInstructions = new Queue<Instruction>();
42            foreach (var instruction in oldInstructions)
43            {
44                // Intercept only the load field and the load static field instruction
45                if (!ShouldReplace(instruction, method))
46                {
47                    IL.Append(instruction);
48                    continue;
49                }
50
51                Replace(instruction, method, IL);
52            }
53        }
54
55        /// <summary>
56        ///     Adds additional members to the host type.
57        /// </summary>
58        /// <param name="host">The host type.</param>
59        public virtual void AddAdditionalMembers(TypeDefinition host)
60        {
61        }
62
63        /// <summary>
64        ///     Adds additional references to the target module.
65        /// </summary>
66        /// <param name="module">The host module.</param>
67        public virtual void ImportReferences(ModuleDefinition module)
68        {
69        }
70
71        /// <summary>
72        ///     Adds local variables to the <paramref name="hostMethod" />.
73        /// </summary>
74        /// <param name="hostMethod">The target method.</param>
75        public virtual void AddLocals(MethodDefinition hostMethod)
76        {
77        }
78
79
80        /// <summary>
81        ///     Determines whether or not the method rewriter should replace the <paramref name="oldInstruction" />.
82        /// </summary>
83        /// <param name="oldInstruction">The instruction that is currently being evaluated.</param>
84        /// <param name="hostMethod">The method that hosts the current instruction.</param>
85        /// <returns><c>true</c> if the method should be replaced; otherwise, it should return <c>false</c>.</returns>
86        protected abstract bool ShouldReplace(Instruction oldInstruction, MethodDefinition hostMethod);
87
88
89        /// <summary>
90        ///     Replaces the <paramref name="oldInstruction" /> with a new set of <paramref name="IL" /> instructions..
91        /// </summary>
92        /// <param name="oldInstruction">The instruction currently being evaluated.</param>
93        /// <param name="hostMethod">The method that contains the target instruction.</param>
94        /// <param name="IL">The ILProcessor for the target method body.</param>
95        protected abstract void Replace(Instruction oldInstruction, MethodDefinition hostMethod, ILProcessor IL);
96    }
97}