前台代码:
function getData(){
$.ajax({
headers:{"AjaxFlag":"XHR","MethodName":"GetData"},
success:function(data){
$("#result").text(data);
}
});
}
四、优化版页面基类
上面的页面基类功能很少,而且通过反射这样调用的效率很低。这里优化一下:
1.可以支持简单类型的参数。
例如上面的GetData可以是:GetData(string name),通过函数元数据可以获取相关的参数,再根据请求的参数,就可以设置参数了。
2.加入标记属性。
只有被AjaxMethodAttribute标记的属性才能被外部调用。
3.优化反射。
利用缓存,避免每次都根据函数名称去搜索函数信息。
标记属性:
public class AjaxMethodAttribute : Attribute
{
}
缓存对象:
public class CacheMethodInfo
{
public string MethodName { get; set; }
public MethodInfo MethodInfo { get; set; }
public ParameterInfo[] Parameters { get; set; }
}
基类代码:
public class PageBase : Page
{
private static Hashtable _ajaxTable = Hashtable.Synchronized(new Hashtable());
public override void ProcessRequest(HttpContext context)
{
HttpRequest request = context.Request;
if (string.Compare(request.Headers["AjaxFlag"],"XHR",true) == 0)
{
InvokeMethod(request.Headers["MethodName"]);
}
base.ProcessRequest(context);
}
/// <summary>
/// 反射执行函数
/// </summary>
/// <param name="methodName"></param>
private void InvokeMethod(string methodName)
{
if (string.IsNullOrEmpty(methodName))
{
EndRequest("MethodName标记不能为空!");
}
CacheMethodInfo targetInfo = TryGetMethodInfo(methodName);
if (targetInfo == null)
{
EndRequest("找不到合适的方法调用!");
}
try
{
object[] parameters = GetParameters(targetInfo.Parameters);
string data = targetInfo.MethodInfo.Invoke(this, parameters) as string;
EndRequest(data);
}
catch (FormatException)
{
EndRequest("参数类型匹配发生错误!");
}
catch (InvalidCastException)
{
EndRequest("参数类型转换发生错误!");
}
catch (ThreadAbortException)
{
}
catch (Exception e)
{
EndRequest(e.Message);
}
}
/// <summary>
/// 获取函数元数据并缓存
/// </summary>
/// <param name="methodName"></param>
/// <returns></returns>
private CacheMethodInfo TryGetMethodInfo(string methodName)
{
Type type = this.GetType().BaseType;
string cacheKey = type.AssemblyQualifiedName;
Dictionary<string, CacheMethodInfo> dic = _ajaxTable[cacheKey] as Dictionary<string, CacheMethodInfo>;
if (dic == null)
{
dic = new Dictionary<string, CacheMethodInfo>();
MethodInfo[] methodInfos = (from m in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
let ma = m.GetCustomAttributes(typeof(AjaxMethodAttribute), false)
where ma.Length > 0
select m).ToArray();
foreach (var mi in methodInfos)
{
CacheMethodInfo cacheInfo = new CacheMethodInfo();
cacheInfo.MethodName = mi.Name;
cacheInfo.MethodInfo = mi;
cacheInfo.Parameters = mi.GetParameters();
dic.Add(mi.Name, cacheInfo);
}
_ajaxTable.Add(cacheKey, dic);
}
CacheMethodInfo targetInfo = null;
dic.TryGetValue(methodName, out targetInfo);
return targetInfo;
}
/// <summary>
/// 获取函数参数
/// </summary>
/// <param name="parameterInfos"></param>
/// <returns></returns>
private object[] GetParameters(ParameterInfo[] parameterInfos)
{
if (parameterInfos == null || parameterInfos.Length <= 0)
{
return null;
}
HttpRequest request = this.Context.Request;
NameValueCollection nvc = null;
string requestType = request.RequestType;
if (string.Compare("GET", requestType, true) == 0)
{
nvc = request.QueryString;
}
else
{
nvc = request.Form;
}
int length = parameterInfos.Length;
object[] parameters = new object[length];
if (nvc == null || nvc.Count <= 0)
{
return parameters;
}
for (int i = 0; i < length; i++)
{
ParameterInfo pi = parameterInfos[i];
string[] values = nvc.GetValues(pi.Name);
object value = null;
if (values != null)
{
if (values.Length > 1)
{
value = String.Join(",", values);
}
else
{
value = values[0];
}
}
if (value == null)
{
continue;
}
parameters[i] = Convert.ChangeType(value, pi.ParameterType);
}
return parameters;
}
private void EndRequest(string msg)
{
HttpResponse response = this.Context.Response;
response.Write(msg);
response.End();
}
}









