PageRenderTime 103ms CodeModel.GetById 60ms app.highlight 5ms RepoModel.GetById 36ms app.codeStats 0ms

/src/LinFu.IoC/Configuration/BaseMethodBuilder.cs

http://github.com/philiplaureano/LinFu
C# | 101 lines | 45 code | 15 blank | 41 comment | 1 complexity | 2fce02cd61b78a5dea23e1a59de56f86 MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Linq;
  4using System.Reflection;
  5using System.Reflection.Emit;
  6using LinFu.IoC.Configuration.Interfaces;
  7
  8namespace LinFu.IoC.Configuration
  9{
 10    /// <summary>
 11    ///     Represents the default implementation of the <see cref="IMethodBuilder{TMethod}" /> interface.
 12    /// </summary>
 13    /// <typeparam name="TMethod">The method type to generate.</typeparam>
 14    public abstract class BaseMethodBuilder<TMethod> : IMethodBuilder<TMethod>
 15        where TMethod : MethodBase
 16    {
 17        /// <summary>
 18        ///     Creates a method from the <paramref name="existingMethod" />.
 19        /// </summary>
 20        /// <param name="existingMethod">The method that will be used to define the new method.</param>
 21        /// <returns>A method based on the old method.</returns>
 22        public MethodBase CreateMethod(TMethod existingMethod)
 23        {
 24            var returnType = GetReturnType(existingMethod);
 25            var parameterTypes = (from p in existingMethod.GetParameters()
 26                select p.ParameterType).ToArray();
 27
 28            // Determine the method signature
 29            var parameterList = GetParameterList(existingMethod, parameterTypes);
 30
 31            var declaringType = existingMethod.DeclaringType;
 32            var module = declaringType.Module;
 33            var dynamicMethod = new DynamicMethod(string.Empty, returnType, parameterList.ToArray(), module);
 34            var IL = dynamicMethod.GetILGenerator();
 35
 36            // Push the target instance, if necessary
 37            PushInstance(IL, existingMethod);
 38
 39            // Push the method arguments
 40            PushMethodArguments(IL, existingMethod);
 41
 42            // Call the target method
 43            EmitCall(IL, existingMethod);
 44
 45            // Unbox the return type
 46            IL.Emit(OpCodes.Ret);
 47
 48            return dynamicMethod;
 49        }
 50
 51
 52        /// <summary>
 53        ///     Pushes the method arguments onto the stack.
 54        /// </summary>
 55        /// <param name="IL">The <see cref="ILGenerator" /> of the target method body.</param>
 56        /// <param name="targetMethod">The target method that will be invoked.</param>
 57        protected virtual void PushMethodArguments(ILGenerator IL, MethodBase targetMethod)
 58        {
 59            var parameterTypes = (from p in targetMethod.GetParameters()
 60                select p.ParameterType).ToArray();
 61
 62            // Push the method arguments onto the stack
 63            var parameterCount = parameterTypes.Length;
 64            for (var index = 0; index < parameterCount; index++) IL.Emit(OpCodes.Ldarg, index);
 65        }
 66
 67        /// <summary>
 68        ///     Determines the parameter types of the dynamically generated method.
 69        /// </summary>
 70        /// <param name="existingMethod">The target method.</param>
 71        /// <param name="parameterTypes">The target method argument types.</param>
 72        /// <returns>The list of <see cref="System.Type" /> objects that describe the signature of the method to generate.</returns>
 73        protected virtual IList<Type> GetParameterList(TMethod existingMethod, Type[] parameterTypes)
 74        {
 75            return new List<Type>(parameterTypes);
 76        }
 77
 78        /// <summary>
 79        ///     Pushes the method target onto the stack.
 80        /// </summary>
 81        /// <param name="IL">The <see cref="ILGenerator" /> that belongs to the method body.</param>
 82        /// <param name="method">The current method.</param>
 83        protected virtual void PushInstance(ILGenerator IL, TMethod method)
 84        {
 85        }
 86
 87        /// <summary>
 88        ///     Determines the return type from the target <paramref name="method" />.
 89        /// </summary>
 90        /// <param name="method">The target method itself.</param>
 91        /// <returns>The method return type.</returns>
 92        protected abstract Type GetReturnType(TMethod method);
 93
 94        /// <summary>
 95        ///     Emits the instruction to call the target <paramref name="method" />
 96        /// </summary>
 97        /// <param name="IL">The <see cref="ILGenerator" /> of the target method body.</param>
 98        /// <param name="method">The method that will be invoked.</param>
 99        protected abstract void EmitCall(ILGenerator IL, TMethod method);
100    }
101}