PageRenderTime 158ms CodeModel.GetById 80ms app.highlight 18ms RepoModel.GetById 53ms app.codeStats 0ms

/src/LinFu.AOP/Emitters/EmitAfterInvoke.cs

http://github.com/philiplaureano/LinFu
C# | 80 lines | 49 code | 12 blank | 19 comment | 0 complexity | 38575902b3f828019e5b47cf3e81120d MD5 | raw file
 1using LinFu.AOP.Cecil.Interfaces;
 2using LinFu.AOP.Interfaces;
 3using LinFu.Reflection.Emit;
 4using Mono.Cecil;
 5using Mono.Cecil.Cil;
 6
 7namespace LinFu.AOP.Cecil
 8{
 9    /// <summary>
10    ///     Represents a type that emits the call to the <see cref="IAfterInvoke" /> instance.
11    /// </summary>
12    public class EmitAfterInvoke : IInstructionEmitter
13    {
14        private readonly VariableDefinition _invocationInfo;
15        private readonly VariableDefinition _returnValue;
16        private readonly VariableDefinition _surroundingClassImplementation;
17        private readonly VariableDefinition _surroundingImplementation;
18
19        /// <summary>
20        ///     Initializes a new instance of the <see cref="EmitAfterInvoke" /> class.
21        /// </summary>
22        /// <param name="surroundingImplementation">The variable that contains the <see cref="IAroundInvoke" /> instance.</param>
23        /// <param name="surroundingClassImplementation">
24        ///     The variable that contains the class-level <see cref="IAroundInvoke" />
25        ///     instance.
26        /// </param>
27        /// <param name="invocationInfo">The variable that contains the <see cref="IInvocationInfo" /> instance.</param>
28        /// <param name="returnValue">The local vaiable that contains the return value of the target method.</param>
29        public EmitAfterInvoke(VariableDefinition surroundingImplementation,
30            VariableDefinition surroundingClassImplementation,
31            VariableDefinition invocationInfo, VariableDefinition returnValue)
32        {
33            _surroundingImplementation = surroundingImplementation;
34            _surroundingClassImplementation = surroundingClassImplementation;
35            _invocationInfo = invocationInfo;
36            _returnValue = returnValue;
37        }
38
39
40        /// <summary>
41        ///     Emits the call to the <see cref="IAfterInvoke" /> instance.
42        /// </summary>
43        /// <param name="IL">The <see cref="ILProcessor" /> that points to the current method body.</param>
44        public void Emit(ILProcessor IL)
45        {
46            var module = IL.Body.Method.DeclaringType.Module;
47
48            // instanceAroundInvoke.AfterInvoke(info, returnValue);
49            Emit(IL, module, _surroundingImplementation, _invocationInfo, _returnValue);
50
51            // classAroundInvoke.AfterInvoke(info, returnValue);
52            Emit(IL, module, _surroundingClassImplementation, _invocationInfo, _returnValue);
53        }
54
55
56        private static void Emit(ILProcessor IL, ModuleDefinition module,
57            VariableDefinition surroundingImplementation,
58            VariableDefinition invocationInfo,
59            VariableDefinition returnValue)
60        {
61            var skipInvoke = IL.Create(OpCodes.Nop);
62
63            var skipPrint = IL.Create(OpCodes.Nop);
64            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
65            IL.Emit(OpCodes.Brtrue, skipPrint);
66
67            IL.Append(skipPrint);
68            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
69            IL.Emit(OpCodes.Brfalse, skipInvoke);
70
71            var aroundInvoke = module.ImportMethod<IAfterInvoke>("AfterInvoke");
72            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
73            IL.Emit(OpCodes.Ldloc, invocationInfo);
74            IL.Emit(OpCodes.Ldloc, returnValue);
75            IL.Emit(OpCodes.Callvirt, aroundInvoke);
76
77            IL.Append(skipInvoke);
78        }
79    }
80}