Asp.NET Ajax学习笔记(4) -- Ajax.NET源程序分析2
上次写到Ajax.NET库中最为重要的一个类:AjaxRequestProcessor,所有的Ajax请求都是通过该类来处理.该类中只有一个方法,public void Run() ,应该说理解了这个方法,Ajax.NET框架的工作原理就差不多明白了,我是这么想的.我想通过注释的方式来解读这个方法.
publicvoid Run() ...{
//检查当前上下文是否启用了ASP.NET跟踪功能.如果启用了就输出一条跟踪信息.启用跟踪功能可以方便调试.
//如果要启用该功能可以在页面上的Page指令中加Trace,如<%@ Page Trace="true" %>,这样就可以在访问页面时
//看到很多额外的信息.
if ( context.Trace.IsEnabled )
...{
context.Trace.Write( "Ajax.NET", "Begin ProcessRequest" );
}
DateTime now = DateTime.Now;
//得到当前请求的文件名.
string typeName = Path.GetFileNameWithoutExtension( context.Request.FilePath );
if ( Utility.Settings !=null&& Utility.Settings.UrlNamespaceMappings.Contains( typeName ) ) ...{
typeName = Utility.Settings.UrlNamespaceMappings[ typeName ].ToString();
}
//初始化AjaxProcessor类,该类是一个帮助类.主要功能是输出客户端脚本.下面马上就能看到.
AjaxProcessor ajaxer =new AjaxProcessor();
ajaxer.InitializeContext( ref context );
// return the common scripts for this type of processor
// 为该处理类返回通用脚本
//如果该请求的文件名为common,就是专门为了处理页面中的这一行<script language="javascript" src="ajax/common.ashx">
if ( typeName.ToLower() =="common" ) ...{
if ( context.Trace.IsEnabled ) ...{
context.Trace.Write( "Ajax.NET", "Render common Javascript" );
}
//该脚本缓存1分钟,类型为纯文本.
context.Response.Expires =1;
context.Response.ContentType ="text/plain";
/**//*
* 调用AjaxProcessor类中的方法RenderCommonScript,目的是输出ajax.js或ajax_mobile.js这个用于
* 包装和处理由XMLHttpRequest对象生成的Ajax请求.
internal void RenderCommonScript() {
string commonAjax = "ajax.js";
if ( context.Request.UserAgent.IndexOf( "Windows CE; PPC;" ) >= 0 ) {
commonAjax = "ajax_mobile.js"; //该文件用于移动设备.
}
//因为这两个脚本文件已经作为资源编译到程序集中,所以可以用下面的方式直接从程序集中读取.
StreamReader sr = new StreamReader( Assembly.GetCallingAssembly().GetManifestResourceStream( "Ajax." + commonAjax ) );
//Write也是AjaxProcessor类中的帮助方法,其实就是Response.Write方法的封装.
Write( sr.ReadToEnd() );
sr.Close();
//客户端脚本的版本号
Write( "var ajaxVersion = '5.7.22.2';" );
}
*/
ajaxer.RenderCommonScript();
if ( context.Trace.IsEnabled ) ...{
context.Trace.Write( "Ajax.NET", "End ProcessRequest" );
}
//如果是请求通用脚本,那任务已经完成,下面的代码就不用再执行了.返回停止Response.
return;
}
//如果不是请求通用脚本,那就是具体的请求.所以不应该缓存.
context.Response.Expires =0;
context.Response.AddHeader( "cache-control", "no-cache" );
//定义一些变量,为反射做准备.
Type type;
MethodInfo[] mi =null;
string methodName =null;
object[] po =newobject[] ...{};
//这里的typeName的格式是这样的:"NameSapce.Class,Assembly",Type的GetType方法可以接受该参数
//动态取得该类的引用.这是反射的第一步.
type = Type.GetType( typeName );
mi = type.GetMethods(); //读取该类中的所有方法,并保存.
//调用AjaxProcessor类中的GetMethodName方法,就是读取要调用的方法名称.
//该方法名称作为请求的一个参数传递给服务器.类似于这样:http://xxx/xx.ashx?_method=MethodName
//该方法就是读取这里的MethodName.这是反射的第二步,读取要调用的方法.
methodName = ajaxer.GetMethodName();
string md5 =null;
StreamReader sr =null;
//尝试从Cache中读取是否是一模一样的请求,如果是一样的那么返回的值也是一样的,那就节省了调用方法以及处理参数等的开销.
byte[] b =newbyte[context.Request.ContentLength];
if ( context.Request.HttpMethod =="POST"&& context.Request.InputStream.Read( b, 0, b.Length ) >=0 ) ...{
md5 = MD5Helper.GetHash( b );
sr =new StreamReader( new MemoryStream( b ), UTF8Encoding.UTF8 );
if ( context.Cache[ type.FullName +"|"+ md5 ] !=null ) ...{
context.Response.Write( context.Cache[ type.FullName +"|"+ md5 ].ToString() );
// context.Response.Write(""" + md5 + DateTime.Now + """);
if ( context.Trace.IsEnabled ) ...{
context.Trace.Write( "Ajax.NET", "End ProcessRequest" );
}
return;
}
}
//如果请求要调用的方法有AjaxMethodAttribute自定义属性.
//则检查该自定义属性并尝试调用该方法.只有添加该属性的方法才能被调用.
if ( methodName !=null ) ...{
MethodInfo method = type.GetMethod( methodName );//取得该方法
if ( method !=null ) ...{
//尝试读取AjaxmethodAttribute自定义属性.
object[] ii = method.GetCustomAttributes( typeof (AjaxMethodAttribute), true );
if ( ii.Length !=1 ) ...{
// 要调用的方法没有AjaxMethodAttribute自定义属性的话,产生一个异常.
//HandleException也是AjaxProcessor中的一个方法.功能是输出异常信息.以XML文件的形式或者文本形式.
ajaxer.HandleException( new NotImplementedException( "The method '"+ context.Request[ "m" ] +"' is not implemented or access refused." ), null );
if ( context.Trace.IsEnabled ) ...{
context.Trace.Write( "Ajax.NET", "End ProcessRequest" );
}
//产生异常后直接返回.
return;
}
// 设置方法参数.
//先取得要调用的服务器端的方法的参数列表.
ParameterInfo[] para = method.GetParameters();
po =newobject[para.Length];
try...{
//这也是AjaxProcessor类的帮助方法,功能是从传递过去的StreamSeader,sr中或直接从Request URL中读取参数并把值设置到po中.
//该方法的详细说明见AjaxProeCSSor类的注释.
ajaxer.RetreiveParameters( ref sr, para, ref po );
}catch ( Exception ex ) ...{
ajaxer.HandleException( ex, "Could not retreive parameters from HTTP request." );
}
// 尝试调用方法.
object o =null;
try...{
if ( context.Trace.IsEnabled ) ...{
context.Trace.Write( "Ajax.NET", "Invoking "+ type.FullName +"."+ method.Name );
}
//如果这是个静态方法,我们就不用再实例化该类.一些类没有默认构选器.
if ( method.IsStatic ) ...{
try...{
//用反射的方式调用某方法.这是反射的第三步.调用方法.
o = type.InvokeMember(
methodName,
BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase,
null, null, po );
}catch ( Exception ex ) ...{ //catch中的都是异常处理.如果出现异常,报告异常.
if ( ex.InnerException !=null ) ...{
ajaxer.HandleException( ex.InnerException, null );
}else...{
ajaxer.HandleException( ex, null );
}
if ( context.Trace.IsEnabled ) ...{
context.Trace.Write( "Ajax.NET", "End ProcessRequest" );
}
//有异常发生就返回.
return;
}
}else...{
//
来源: http://lib.csdn.net/article/dotnet/44098