PageRenderTime 82ms CodeModel.GetById 60ms app.highlight 5ms RepoModel.GetById 15ms app.codeStats 0ms

/src/LinFu.IoC/Configuration/BaseMethodInvoke.cs

http://github.com/philiplaureano/LinFu
C# | 113 lines | 56 code | 17 blank | 40 comment | 3 complexity | db966b4fd31c7ae69c377d6ade78f79e MD5 | raw file
  1using System.Collections.Generic;
  2using System.Reflection;
  3using System.Reflection.Emit;
  4using LinFu.IoC.Configuration.Interfaces;
  5using LinFu.IoC.Interfaces;
  6using LinFu.Reflection;
  7
  8namespace LinFu.IoC.Configuration
  9{
 10    /// <summary>
 11    ///     Represents the default implementation of the <see cref="IMethodInvoke{TMethod}" /> interface.
 12    /// </summary>
 13    public abstract class BaseMethodInvoke<TMethod> : IMethodInvoke<TMethod>, IInitialize
 14        where TMethod : MethodBase
 15    {
 16        private static readonly Dictionary<TMethod, MethodBase> _cache = new Dictionary<TMethod, MethodBase>();
 17
 18        /// <summary>
 19        ///     Initializes the class with the default values.
 20        /// </summary>
 21        public BaseMethodInvoke()
 22        {
 23            // HACK: Set the ReflectionMethodBuilder as the default builder
 24            if (typeof(TMethod) == typeof(MethodInfo))
 25                MethodBuilder = new ReflectionMethodBuilder<MethodInfo>() as IMethodBuilder<TMethod>;
 26        }
 27
 28        /// <summary>
 29        ///     Gets or sets the value indicating the method builder that will be used to
 30        ///     create the target method.
 31        /// </summary>
 32        protected IMethodBuilder<TMethod> MethodBuilder { get; set; }
 33
 34
 35        /// <summary>
 36        ///     Initializes the class with the <paramref name="source">source service container.</paramref>
 37        /// </summary>
 38        /// <param name="source">The <see cref="IServiceContainer" /> instance that will initialize this class.</param>
 39        public void Initialize(IServiceContainer source)
 40        {
 41            MethodBuilder = source.GetService<IMethodBuilder<TMethod>>();
 42        }
 43
 44
 45        /// <summary>
 46        ///     Instantiates an object instance with the <paramref name="targetMethod" />
 47        ///     and <paramref name="arguments" />.
 48        /// </summary>
 49        /// <param name="target">The target object reference. In this particular case, this parameter will be ignored.</param>
 50        /// <param name="targetMethod">The target method.</param>
 51        /// <param name="arguments">The arguments to be used with the method.</param>
 52        /// <returns>An object reference that represents the method return value.</returns>
 53        public object Invoke(object target, TMethod targetMethod,
 54            object[] arguments)
 55        {
 56            object result = null;
 57
 58            // Reuse the cached results, if possible
 59            if (!_cache.ContainsKey(targetMethod))
 60                GenerateTargetMethod(targetMethod);
 61
 62            var factoryMethod = _cache[targetMethod];
 63
 64            try
 65            {
 66                result = DoInvoke(target, targetMethod, factoryMethod, arguments);
 67            }
 68            catch (TargetInvocationException ex)
 69            {
 70                throw ex.InnerException;
 71            }
 72
 73            return result;
 74        }
 75
 76
 77        /// <summary>
 78        ///     Invokes the <paramref name="targetMethod" /> with the given <paramref name="arguments" />.
 79        /// </summary>
 80        /// <param name="target">The target instance.</param>
 81        /// <param name="originalMethod">The original method that describes the target method.</param>
 82        /// <param name="targetMethod">The actual method that will be invoked.</param>
 83        /// <param name="arguments">The method arguments.</param>
 84        /// <returns>The return value from the target method.</returns>
 85        protected virtual object DoInvoke(object target, TMethod originalMethod, MethodBase targetMethod,
 86            object[] arguments)
 87        {
 88            var result = targetMethod.Invoke(target, arguments);
 89
 90            return result;
 91        }
 92
 93        /// <summary>
 94        ///     Creates a <see cref="DynamicMethod" /> that will be used as the
 95        ///     factory method and stores it in the method cache.
 96        /// </summary>
 97        /// <param name="targetMethod">The constructor that will be used to instantiate the target type.</param>
 98        protected virtual void GenerateTargetMethod(TMethod targetMethod)
 99        {
100            MethodBase result = null;
101
102            // HACK: Since the Mono runtime does not yet implement the DynamicMethod class,
103            // we'll actually have to use the constructor itself to construct the target type            
104            result = Runtime.IsRunningOnMono ? targetMethod : MethodBuilder.CreateMethod(targetMethod);
105
106            // Save the results
107            lock (_cache)
108            {
109                _cache[targetMethod] = result;
110            }
111        }
112    }
113}