ASP.NET MVC - 漫谈ActionMethodDispatcher
来源:互联网 发布:新东方网络课 编辑:程序博客网 时间:2024/06/07 04:51
跳过ASP.NET MVC中所有的路由映射和各种有的没的缓存机制,一个个请求从发送到处理,最终是由Action去执行的,而在ASP.NET MVC中,Action的最终执行者叫做ActionMethodDispacher。
在这篇文章中,我想从无到有地建立一个Dispatcher,顺便窥探一下ASP.NET MVC中Action的执行机制。
在没有看源码之前,我觉得这个Dispatcher没有什么了不起,不就是个动态函数调用嘛,使用反射调用不就就行了,几行代码随便搞定:
public class ReflectionDispatcher { public MethodInfo MethodInfo {get;set;} public ReflectionDispatcher(MethodInfo methodInfo) { MethodInfo = methodInfo; } public object Execute(TestClass instance, object[] parameters) { return MethodInfo.Invoke(instance, parameters); } }
多么简单,简直就是一目了然,为了这么点功能,建一个类简直就是多余!
但是,如果ASP.NET MVC中的ActionMethodDispacher也是这样实现的话,那么...嘿嘿,估计会被人骂的很惨吧。
原因是这个ReflectDispacher的性能非常低下,不是因为代码写得太差,只是因为反射调用先天不足,本来就有性能的瓶颈。
关于如何高效动态调用函数,这里就不多说了,详见:http://www.codeproject.com/Articles/14593/A-General-Fast-Method-Invoker
下面我试着仿照ASP.NET MVC的ActionMethodDispacher来建一个性能高点的Dispacher,至于性能可以高多少,不妨等下做个小试验。
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Reflection;using System.Linq.Expressions;namespace MvcConsole{ public class ActionMethodDispatcher { private delegate object ActionExecutor(TestClass instance, object[] parameters); private delegate void VoidActionExecutor(TestClass instance, object[] parameters); private ActionExecutor _executor; private static ActionExecutor BuildActionExecutor(MethodInfo method) { ParameterExpression instanceParameter = Expression.Parameter(typeof(TestClass), "instance"); ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters"); List<Expression> parameters = new List<Expression>(); ParameterInfo[] parameterInfos = method.GetParameters(); for (int i = 0; i < parameterInfos.Length; i++) { ParameterInfo paramInfo = parameterInfos[i]; BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i)); UnaryExpression valueCast = Expression.Convert(valueObj, paramInfo.ParameterType); parameters.Add(valueCast); } MethodCallExpression methodCall = Expression.Call(instanceParameter, method, parameters); return methodCall.Type == typeof(void) ? WrapVoidAction(Expression.Lambda<VoidActionExecutor>(methodCall, instanceParameter, parametersParameter).Compile()) : Expression.Lambda<ActionExecutor>(methodCall, instanceParameter, parametersParameter).Compile(); } public ActionMethodDispatcher(MethodInfo methodInfo) { _executor = BuildActionExecutor(methodInfo); } public object Execute(TestClass instance, object[] parameters) { return _executor(instance, parameters); } private static ActionExecutor WrapVoidAction(VoidActionExecutor executor) { return (instance, parameters) => { executor(instance, parameters); return null; }; } }}
从这个代码中,我们明显可以看到,这个Dispacher貌似要“胖”很多。
下面就来比较下两个Dispatcher的性能:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Reflection;using System.Linq.Expressions;using System.Diagnostics;namespace MvcConsole{ public class TestClass { public String State { get; set; } public TestClass() { State = "Init"; } public void PrintObjects(String para1, String para2) { } } class Program { static void Main(string[] args) { Stopwatch stopWatch = new Stopwatch(); int times = 10000000; var dispatcher = new ActionMethodDispatcher(typeof(TestClass).GetMethod("PrintObjects")); var testClass = new TestClass(); testClass.State = "Expression Call"; stopWatch.Start(); for (int i = 0; i < times; i++) { dispatcher.Execute(testClass, new object[] { "Hello", "World" }); } stopWatch.Stop(); Console.WriteLine("Expression Call use: " + stopWatch.Elapsed); var mydispatcher = new RelectionDispatcher(typeof(TestClass).GetMethod("PrintObjects")); testClass.State = "Reflect Call"; stopWatch.Reset(); stopWatch.Start(); for (int i = 0; i < times; i++) { mydispatcher.Execute(testClass, new object[] { "Hello", "World" }); } stopWatch.Stop(); Console.WriteLine("Reflect Call use: " + stopWatch.Elapsed); } }}
运行结果:
Expression Call use: 00:00:00.3916032
Reflect Call use: 00:00:09.4091986
ActionMethodDispatcher的性能要比ReflectDispatcher的性能高20多倍。好吧,这次Reflect的调用真是完败啊,为了这20多倍的性能,我们就是再多写20多倍的代码也在所不惜啊。
- ASP.NET MVC - 漫谈ActionMethodDispatcher
- ASP.net服务器控件漫谈
- 漫谈 asp.net 之一:Access denied 错误
- 漫谈 asp.net 之二:Caching
- 漫谈ASP.NET 页面对象模型
- 漫谈Ajax在ASP.Net中的使用
- 漫谈Ajax在ASP.Net中的使用
- ASP.NET MVC 框架
- ASP.NET MVC 框架
- ASP.NET MVC
- ASP.NET MVC框架
- ASP.NET MVC框架
- ASP.NET MVC
- Asp.Net Mvc Study
- ASP.NET MVC框架
- Asp.Net MVC 概述
- Asp.Net MVC 控制器
- Asp.Net MVC 路由
- linux下安装hadoop-2.0.0-alpha(双namenode federation)安装过程整理
- C#向共享文件夹上传及下载文件
- VC实现查找纯真数据库
- 树状数组 经理的烦恼
- SQL ordered by Version Count
- ASP.NET MVC - 漫谈ActionMethodDispatcher
- 關于在WIN32調用一些Zw系列的文件操作函數.
- IOS学习笔记20—UIActivityIndicatorView、UIProgressView
- 实例repeater 分页、表头不动、添加列序号、日期分隔符转换(datareader存储过程实现)
- How to: Debug a Release Build (vs2010级以上版本Release下调试设置)
- Error C2662, cannot convert ‘this’ pointer from ‘const class ’ to ‘class &’
- PCI配置空间简介
- iphone 开发中 拨打电话等的操作
- Objective-C新特性