1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation. All rights reserved.
\r
5 * This software is subject to the Microsoft Public License (Ms-PL).
\r
6 * A copy of the license can be found in the license.htm file included
\r
7 * in this distribution.
\r
9 * You must not remove this notice, or any other, from this software.
\r
11 * ***************************************************************************/
\r
13 namespace System.Web.Mvc {
\r
15 using System.Collections.Generic;
\r
16 using System.Linq.Expressions;
\r
17 using System.Reflection;
\r
19 // The methods in this class don't perform error checking; that is the responsibility of the
\r
21 internal sealed class ActionMethodDispatcher {
\r
23 private delegate object ActionExecutor(ControllerBase controller, object[] parameters);
\r
24 private delegate void VoidActionExecutor(ControllerBase controller, object[] parameters);
\r
26 private ActionExecutor _executor;
\r
28 public ActionMethodDispatcher(MethodInfo methodInfo) {
\r
29 _executor = GetExecutor(methodInfo);
\r
30 MethodInfo = methodInfo;
\r
33 public MethodInfo MethodInfo {
\r
38 public object Execute(ControllerBase controller, object[] parameters) {
\r
39 return _executor(controller, parameters);
\r
42 private static ActionExecutor GetExecutor(MethodInfo methodInfo) {
\r
43 // Parameters to executor
\r
44 ParameterExpression controllerParameter = Expression.Parameter(typeof(ControllerBase), "controller");
\r
45 ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
\r
47 // Build parameter list
\r
48 List<Expression> parameters = new List<Expression>();
\r
49 ParameterInfo[] paramInfos = methodInfo.GetParameters();
\r
50 for (int i = 0; i < paramInfos.Length; i++) {
\r
51 ParameterInfo paramInfo = paramInfos[i];
\r
52 BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
\r
53 UnaryExpression valueCast = Expression.Convert(valueObj, paramInfo.ParameterType);
\r
55 // valueCast is "(Ti) parameters[i]"
\r
56 parameters.Add(valueCast);
\r
60 UnaryExpression instanceCast = (!methodInfo.IsStatic) ? Expression.Convert(controllerParameter, methodInfo.ReflectedType) : null;
\r
61 MethodCallExpression methodCall = methodCall = Expression.Call(instanceCast, methodInfo, parameters);
\r
63 // methodCall is "((TController) controller) method((T0) parameters[0], (T1) parameters[1], ...)"
\r
65 if (methodCall.Type == typeof(void)) {
\r
66 Expression<VoidActionExecutor> lambda = Expression.Lambda<VoidActionExecutor>(methodCall, controllerParameter, parametersParameter);
\r
67 VoidActionExecutor voidExecutor = lambda.Compile();
\r
68 return WrapVoidAction(voidExecutor);
\r
71 // must coerce methodCall to match ActionExecutor signature
\r
72 UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));
\r
73 Expression<ActionExecutor> lambda = Expression.Lambda<ActionExecutor>(castMethodCall, controllerParameter, parametersParameter);
\r
74 return lambda.Compile();
\r
78 private static ActionExecutor WrapVoidAction(VoidActionExecutor executor) {
\r
79 return delegate(ControllerBase controller, object[] parameters) {
\r
80 executor(controller, parameters);
\r