PageRenderTime 123ms CodeModel.GetById 60ms app.highlight 5ms RepoModel.GetById 55ms app.codeStats 0ms

/src/LinFu.AOP/Emitters/EmitBeforeInvoke.cs

http://github.com/philiplaureano/LinFu
C# | 99 lines | 54 code | 16 blank | 29 comment | 1 complexity | d23f339052353794dfa96e991ac3305f MD5 | raw file
 1using System;
 2using LinFu.AOP.Cecil.Interfaces;
 3using LinFu.AOP.Interfaces;
 4using LinFu.Reflection.Emit;
 5using Mono.Cecil.Cil;
 6
 7namespace LinFu.AOP.Cecil
 8{
 9    /// <summary>
10    ///     Represents a type that emits the call to the <see cref="IBeforeInvoke" /> instance.
11    /// </summary>
12    public class EmitBeforeInvoke : IInstructionEmitter
13    {
14        private readonly VariableDefinition _invocationInfo;
15        private readonly Type _registryType;
16        private readonly VariableDefinition _surroundingClassImplementation;
17        private readonly VariableDefinition _surroundingImplementation;
18
19        /// <summary>
20        ///     Initializes a new instance of the <see cref="EmitBeforeInvoke" /> class.
21        /// </summary>
22        /// <param name="invocationInfo">The variable that contains the <see cref="IInvocationInfo" /> instance.</param>
23        /// <param name="surroundingClassImplementation">
24        ///     The variable that contains the class-level <see cref="IAroundInvoke" />
25        ///     instance.
26        /// </param>
27        /// <param name="surroundingImplementation">
28        ///     The variable that contains the instance-level <see cref="IAroundInvoke" />
29        ///     instance.
30        /// </param>
31        /// <param name="registryType">
32        ///     The interception registry type that will be responsible for handling class-level
33        ///     interception events.
34        /// </param>
35        public EmitBeforeInvoke(VariableDefinition invocationInfo,
36            VariableDefinition surroundingClassImplementation,
37            VariableDefinition surroundingImplementation,
38            Type registryType)
39        {
40            _invocationInfo = invocationInfo;
41            _surroundingClassImplementation = surroundingClassImplementation;
42            _surroundingImplementation = surroundingImplementation;
43            _registryType = registryType;
44        }
45
46
47        /// <summary>
48        ///     Emits the call to the <see cref="IAfterInvoke" /> instance.
49        /// </summary>
50        /// <param name="IL">The <see cref="ILProcessor" /> that points to the current method body.</param>
51        public void Emit(ILProcessor IL)
52        {
53            var targetMethod = IL.Body.Method;
54            var declaringType = targetMethod.DeclaringType;
55            var module = declaringType.Module;
56
57            var getSurroundingClassImplementation = new GetSurroundingClassImplementation(_invocationInfo,
58                _surroundingClassImplementation,
59                _registryType.GetMethod(
60                    "GetSurroundingImplementation"));
61
62            // var classAroundInvoke = AroundInvokeRegistry.GetSurroundingImplementation(info);           
63            getSurroundingClassImplementation.Emit(IL);
64
65            // classAroundInvoke.BeforeInvoke(info);
66            var skipInvoke = IL.Create(OpCodes.Nop);
67
68            IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation);
69            IL.Emit(OpCodes.Brfalse, skipInvoke);
70
71            var beforeInvoke = module.ImportMethod<IBeforeInvoke>("BeforeInvoke");
72
73            // surroundingImplementation.BeforeInvoke(invocationInfo);
74            IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation);
75            IL.Emit(OpCodes.Ldloc, _invocationInfo);
76            IL.Emit(OpCodes.Callvirt, beforeInvoke);
77
78            IL.Append(skipInvoke);
79
80            // if (surroundingImplementation != null) {
81            if (!targetMethod.HasThis)
82                return;
83
84            var skipInvoke1 = IL.Create(OpCodes.Nop);
85            IL.Emit(OpCodes.Ldloc, _surroundingImplementation);
86            IL.Emit(OpCodes.Brfalse, skipInvoke1);
87
88            var beforeInvoke1 = module.ImportMethod<IBeforeInvoke>("BeforeInvoke");
89
90            // surroundingImplementation.BeforeInvoke(invocationInfo);
91            IL.Emit(OpCodes.Ldloc, _surroundingImplementation);
92            IL.Emit(OpCodes.Ldloc, _invocationInfo);
93            IL.Emit(OpCodes.Callvirt, beforeInvoke1);
94
95            IL.Append(skipInvoke1);
96            // }
97        }
98    }
99}