PageRenderTime 20ms CodeModel.GetById 7ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/src/LinFu.IoC/Reflection/LateBoundExtensions.cs

http://github.com/philiplaureano/LinFu
C# | 184 lines | 88 code | 22 blank | 74 comment | 16 complexity | 0c7f4a884425aaa2a6c9a3acd617f8ee MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Linq;
  4using System.Reflection;
  5using LinFu.IoC.Configuration;
  6using LinFu.IoC.Configuration.Interfaces;
  7using LinFu.IoC.Interfaces;
  8
  9namespace LinFu.IoC.Reflection
 10{
 11    /// <summary>
 12    ///     A class that adds late binding support to any CLR object.
 13    /// </summary>
 14    public static class LateBoundExtensions
 15    {
 16        private static readonly IServiceContainer _container = new ServiceContainer();
 17
 18        static LateBoundExtensions()
 19        {
 20            _container.LoadFromBaseDirectory("*.dll");
 21        }
 22
 23        /// <summary>
 24        ///     Invokes a method on the target <paramref name="instance" />.
 25        /// </summary>
 26        /// <param name="instance">The target instance that will be used to invoke the method.</param>
 27        /// <param name="methodName">The name of the target method.</param>
 28        /// <param name="arguments">The arguments that will be passed to the target method.</param>
 29        /// <returns>The method return value.</returns>
 30        public static object Invoke(this object instance, string methodName, params object[] arguments)
 31        {
 32            if (instance == null)
 33                throw new NullReferenceException("instance");
 34
 35            var context = new MethodFinderContext(arguments);
 36            return Invoke(instance, methodName, context);
 37        }
 38
 39        /// <summary>
 40        ///     Invokes a method on the target <paramref name="instance" /> using the given <paramref name="methodName" /> and
 41        ///     <paramref name="context" />.
 42        /// </summary>
 43        /// <param name="instance">The target instance.</param>
 44        /// <param name="methodName">The name of the target method.</param>
 45        /// <param name="context">The <see cref="IMethodFinderContext" /> that describes the target method.</param>
 46        /// <returns>The method return value.</returns>
 47        public static object Invoke(this object instance, string methodName, MethodFinderContext context)
 48        {
 49            var targetType = instance.GetType();
 50            var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic;
 51
 52            // Group the methods by name
 53            var methodMap = new Dictionary<string, List<MethodInfo>>();
 54            var methods = targetType.GetMethods(flags);
 55            foreach (var method in methods)
 56            {
 57                var name = method.Name;
 58                if (!methodMap.ContainsKey(name))
 59                    methodMap[name] = new List<MethodInfo>();
 60
 61                var currentList = methodMap[name];
 62                currentList.Add(method);
 63            }
 64
 65            var targetMethods = methodMap.ContainsKey(methodName)
 66                ? methodMap[methodName]
 67                : new MethodInfo[0].ToList();
 68            var finder = _container.GetService<IMethodFinder<MethodInfo>>();
 69
 70            var targetMethod = finder.GetBestMatch(targetMethods, context);
 71
 72            // Search the methods that match the given method name
 73            if (targetMethod == null || targetMethods.Count == 0)
 74            {
 75                var message = string.Format("Method '{0}' not found on type '{1}'", methodName, targetType);
 76                throw new ArgumentException(message, "methodName");
 77            }
 78
 79            // Instantiate the generic method, if necessary
 80            if (targetMethod.ContainsGenericParameters)
 81                targetMethod = targetMethod.MakeGenericMethod(context.TypeArguments.ToArray());
 82
 83            var invoker = _container.GetService<IMethodInvoke<MethodInfo>>();
 84
 85            return invoker.Invoke(instance, targetMethod, context.Arguments.ToArray());
 86        }
 87
 88        /// <summary>
 89        ///     Invokes a method on the target <paramref name="instance" /> using the given <paramref name="methodName" />.
 90        /// </summary>
 91        /// <param name="instance">The target instance.</param>
 92        /// <param name="methodName">The name of the target method.</param>
 93        /// <typeparam name="T1">The type argument that will be passed to the target method</typeparam>
 94        /// .
 95        /// <param name="arguments">The arguments that will be passed to the target method.</param>
 96        /// <returns>The method return value.</returns>
 97        public static object Invoke<T1>(this object instance, string methodName, params object[] arguments)
 98        {
 99            if (instance == null)
100                throw new NullReferenceException("instance");
101
102            var context = new MethodFinderContext(new[] {typeof(T1)}, arguments, null);
103            return Invoke(instance, methodName, context);
104        }
105
106        /// <summary>
107        ///     Invokes a method on the target <paramref name="instance" /> using the given <paramref name="methodName" />.
108        /// </summary>
109        /// <param name="instance">The target instance.</param>
110        /// <param name="methodName">The name of the target method.</param>
111        /// <typeparam name="T1">The first type argument that will be passed to the target method</typeparam>
112        /// .
113        /// <typeparam name="T2">The second type argument that will be passed to the target method</typeparam>
114        /// .
115        /// <param name="arguments">The arguments that will be passed to the target method.</param>
116        /// <returns>The method return value.</returns>
117        public static object Invoke<T1, T2>(this object instance, string methodName, params object[] arguments)
118        {
119            if (instance == null)
120                throw new NullReferenceException("instance");
121
122            var typeArguments = new[] {typeof(T1), typeof(T2)};
123            return Invoke(instance, methodName, typeArguments, arguments);
124        }
125
126        /// <summary>
127        ///     Invokes a method on the target <paramref name="instance" /> using the given <paramref name="methodName" />.
128        /// </summary>
129        /// <param name="instance">The target instance.</param>
130        /// <param name="methodName">The name of the target method.</param>
131        /// <typeparam name="T1">The first type argument that will be passed to the target method</typeparam>
132        /// .
133        /// <typeparam name="T2">The second type argument that will be passed to the target method</typeparam>
134        /// .
135        /// <typeparam name="T3">The third type argument that will be passed to the target method.</typeparam>
136        /// <param name="arguments">The arguments that will be passed to the target method.</param>
137        /// <returns>The method return value.</returns>
138        public static object Invoke<T1, T2, T3>(this object instance, string methodName, params object[] arguments)
139        {
140            if (instance == null)
141                throw new NullReferenceException("instance");
142
143            var typeArguments = new[] {typeof(T1), typeof(T2), typeof(T3)};
144            return Invoke(instance, methodName, typeArguments, arguments);
145        }
146
147        /// <summary>
148        ///     Invokes a method on the target <paramref name="instance" /> using the given <paramref name="methodName" />.
149        /// </summary>
150        /// <param name="instance">The target instance.</param>
151        /// <param name="methodName">The name of the target method.</param>
152        /// <typeparam name="T1">The first type argument that will be passed to the target method</typeparam>
153        /// .
154        /// <typeparam name="T2">The second type argument that will be passed to the target method</typeparam>
155        /// .
156        /// <typeparam name="T3">The third type argument that will be passed to the target method.</typeparam>
157        /// <typeparam name="T4">The fourth type argument that will be passed to the target method.</typeparam>
158        /// <param name="arguments">The arguments that will be passed to the target method.</param>
159        /// <returns>The method return value.</returns>
160        public static object Invoke<T1, T2, T3, T4>(this object instance, string methodName, params object[] arguments)
161        {
162            if (instance == null)
163                throw new NullReferenceException("instance");
164
165            var typeArguments = new[] {typeof(T1), typeof(T2), typeof(T3), typeof(T4)};
166            return Invoke(instance, methodName, typeArguments, arguments);
167        }
168
169        /// <summary>
170        ///     Invokes a method on the target <paramref name="instance" /> using the given <paramref name="methodName" />.
171        /// </summary>
172        /// <param name="instance">The target instance.</param>
173        /// <param name="methodName">The name of the target method.</param>
174        /// <param name="typeArguments">The type arguments that will be passed to the target method.</param>
175        /// <param name="arguments">The arguments that will be passed to the target method.</param>
176        /// <returns>The method return value.</returns>
177        public static object Invoke(this object instance, string methodName, Type[] typeArguments,
178            params object[] arguments)
179        {
180            var context = new MethodFinderContext(typeArguments, arguments, null);
181            return Invoke(instance, methodName, context);
182        }
183    }
184}