PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/SystemWebMvc/Mvc/ActionMethodDispatcher.cs

https://bitbucket.org/markhneedham/aspnet-mvc
C# | 75 lines | 53 code | 13 blank | 9 comment | 4 complexity | ab272527af96851a31a441f7d02f26e6 MD5 | raw file
  1. namespace System.Web.Mvc {
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq.Expressions;
  6. using System.Reflection;
  7. // The methods in this class don't perform error checking; that is the responsibility of the
  8. // caller.
  9. internal sealed class ActionMethodDispatcher {
  10. private delegate object ActionExecutor(ControllerBase controller, object[] parameters);
  11. private delegate void VoidActionExecutor(ControllerBase controller, object[] parameters);
  12. private ActionExecutor _executor;
  13. public ActionMethodDispatcher(MethodInfo methodInfo) {
  14. _executor = GetExecutor(methodInfo);
  15. MethodInfo = methodInfo;
  16. }
  17. public MethodInfo MethodInfo {
  18. get;
  19. private set;
  20. }
  21. public object Execute(ControllerBase controller, object[] parameters) {
  22. return _executor(controller, parameters);
  23. }
  24. private static ActionExecutor GetExecutor(MethodInfo methodInfo) {
  25. // Parameters to executor
  26. ParameterExpression controllerParameter = Expression.Parameter(typeof(ControllerBase), "controller");
  27. ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
  28. // Build parameter list
  29. List<Expression> parameters = new List<Expression>();
  30. ParameterInfo[] paramInfos = methodInfo.GetParameters();
  31. for (int i = 0; i < paramInfos.Length; i++) {
  32. ParameterInfo paramInfo = paramInfos[i];
  33. BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
  34. UnaryExpression valueCast = Expression.Convert(valueObj, paramInfo.ParameterType);
  35. // valueCast is "(Ti) parameters[i]"
  36. parameters.Add(valueCast);
  37. }
  38. // Call method
  39. UnaryExpression controllerCast = Expression.Convert(controllerParameter, methodInfo.ReflectedType);
  40. MethodCallExpression methodCall = Expression.Call(controllerCast, methodInfo, parameters);
  41. // methodCall is "((TController) controller) method((T0) parameters[0], (T1) parameters[1], ...)"
  42. // Create function
  43. if (methodCall.Type == typeof(void)) {
  44. Expression<VoidActionExecutor> lambda = Expression.Lambda<VoidActionExecutor>(methodCall, controllerParameter, parametersParameter);
  45. VoidActionExecutor voidExecutor = lambda.Compile();
  46. return WrapVoidAction(voidExecutor);
  47. }
  48. else {
  49. // must coerce methodCall to match ActionExecutor signature
  50. UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));
  51. Expression<ActionExecutor> lambda = Expression.Lambda<ActionExecutor>(castMethodCall, controllerParameter, parametersParameter);
  52. return lambda.Compile();
  53. }
  54. }
  55. private static ActionExecutor WrapVoidAction(VoidActionExecutor executor) {
  56. return delegate(ControllerBase controller, object[] parameters) {
  57. executor(controller, parameters);
  58. return null;
  59. };
  60. }
  61. }
  62. }