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