zoukankan      html  css  js  c++  java
  • 反射+特性打造简洁的AJAX调用

    这里我要实现类似AjaxPro组件调用效果的功能,先看看AjaxPro在CS文件中的代码是怎么写的。

    //在后台写的有参方法
    
    [AjaxPro.AjaxMethod]
    
    public string getString(string str)
    
    {
    
    return str + "Say: hello my friends";
    
    }

    前台页面的调用方式

    function Button4_onclick() {
    
    var str=document.getElementByIdx_x("<%=TextBox1.ClientID %>").value;
    
    WebUI._Default.getString(str,getStringCallBack);
    
    }

    这样的调用代码相当于在客户端直接执行了服务器端代码,然后取到执行结果,是不是有点意思,接下来我们就来自己把这类似的功能实现一把。

    不过在实现之前你最好对反射和特性的基本运用有一定的了解,马上进入正题。

    首先我们来理一下实现的思路

    1.定义能应用在方法上的Ajax标识特性,因为并不是Page对象的所有方法都需要公开被调用,可以用特性做一个标记,可以通过MethodAliasName属性为方法设置一个方法别名,这样做的目的主要是为了安全和AJAX调用代码更简洁。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace AjaxInvokeDemo.Ajax
    {
        [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
        public class AjaxMethodAttribute : Attribute
        {
            /// <summary>
            /// 设置ajax调用时的方法别名
            /// </summary>
            public string MethodAliasName
            {
                get;
                set;
            }
        }
    }

    2.定义页面基类,在里面实现一些公用的逻辑。比如获取要执行的方法的名称以及方法的参数,并通过反射对方法进行调用。具体还是看代码吧,可能更清楚一点。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.Runtime;
    using System.Reflection;
    using System.Collections.Specialized;
    namespace ConfigDemo.Ajax
    {
        public abstract class AjaxPage<T> : System.Web.UI.Page
        {
            private static readonly string AjaxMethodCacheName = "AjaxMethods";
            private string pageName = typeof(T).Name;
            private Type pageType = typeof(T);
           
            protected override void OnPreInit(EventArgs e)
            {
                if (Cache[AjaxMethodCacheName] == null)
                {
                    AjaxMethods = AjaxHelper.GetAjaxMethods<T>();
                    Cache[AjaxMethodCacheName] = AjaxMethods;
                }
                else
                {
                    AjaxMethods = Cache[AjaxMethodCacheName] as Dictionary<string, string>;
                }
                base.OnPreInit(e);
            }
    
            protected override void OnLoad(EventArgs e)
            {
                ExecuteAction();
                base.OnLoad(e);
            }
    
            public Dictionary<string, string> AjaxMethods
            {
                get;
                set;
            }
    
            /// <summary>
            /// Action名称或者别名
            /// </summary>
            public string CurrentActionName
            {
                get
                {
                    if (!string.IsNullOrEmpty(HttpContext.Current.Request["action"]))
                    {
                        return HttpContext.Current.Request["action"];
                    }
                    throw new Exception("调用时必须指定Action参数..");
                }
            }
    
            /// <summary>
            /// 传递的参数集合
            /// </summary>
            public object[] CurrentParams
            {
                //一般的调用URL格式为 http://xxxxx/yyy.aspx?action=method&id=a001 ...
                get
                {
                    NameValueCollection NVs = HttpContext.Current.Request.QueryString;
                    object[] objs = new object[NVs.Count-1]; //这里将action参数排除在外
                    for(int i =1;i<NVs.Count; i++)
                    {
                        objs[i-1] = NVs[i];
                    }
    
                    return objs;
                } 
            }
    
            /// <summary>
            /// 最终要执行的Page的方法的真实名称
            /// </summary>
            public string CurrentAjaxMethodName
            {
                get;
                set;
            }
    
            public void ExecuteAction()
            {
                if (!AjaxMethods.ContainsKey(CurrentActionName) && !AjaxMethods.ContainsValue(CurrentActionName))
                {
                    throw new Exception("调用的方法不存在或者未被公开为Ajax方法..");
                }
    
                //没有为Ajax方法指定别名
                if (AjaxMethods.ContainsKey(CurrentActionName) && AjaxMethods[CurrentActionName] == CurrentActionName)
                {
                    CurrentAjaxMethodName = CurrentActionName;
                }
                else
                {
                    //为Ajax方法指定了别名
                    CurrentAjaxMethodName = AjaxMethods.First<KeyValuePair<string, string>>(x => x.Value == CurrentActionName).Key;
                }
    
                MethodInfo method = pageType.GetMethod(CurrentAjaxMethodName);
                if (method != null)
                {
                    object PageObj = GetPageInstance();
                    method.Invoke(PageObj, CurrentParams);
                }
                
            }
    
    
            public object GetPageInstance()
            {
    
                if (Cache[pageName] == null)
                {
                    object PageObj = Activator.CreateInstance(pageType);
                    return Cache[pageName] = PageObj;
                }
                else
                {
                    return Cache[pageName] as object;
                }
            }
    
    
            
        }
    }

    3.为了获取被标识为AjaxMethod的方法集合,这里专门用一个AjaxHelper类实现。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.Reflection;
    namespace ConfigDemo.Ajax
    {
        public class AjaxHelper
        {
            /// <summary>
            /// 获取指定Page对象中标记为Ajax的方法集合
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="page"></param>
            /// <returns></returns>
            public static Dictionary<string,string> GetAjaxMethods<T>()
            {
                Dictionary<string, string> ajaxMethods = new Dictionary<string, string>();
                AjaxMethodAttribute ajaxMethodAttribute = null;
                //方法别名
                string methodAliasName = string.Empty;
               
                Type t = typeof(T);
                MethodInfo[] methods = t.GetMethods();
                foreach (MethodInfo method in methods)
                {
                    object[] attributes = method.GetCustomAttributes(typeof(AjaxMethodAttribute), false);
                    if (attributes != null && attributes.Length > 0)
                    {
                        ajaxMethodAttribute = (AjaxMethodAttribute)attributes[0];
                        //如果没有为ajax调用方法设置别名则用方法本身的名称
                        methodAliasName = string.IsNullOrEmpty(ajaxMethodAttribute.MethodAliasName) == true ? method.Name : ajaxMethodAttribute.MethodAliasName;
                        ajaxMethods.Add(method.Name, methodAliasName);
                    }
                }
    
                return ajaxMethods;
            }
        }
    }

    4.基础框架搭建完毕,看看怎么使用

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    using System.Reflection;
    using System.Text;
    
    namespace AjaxInvokeDemo.Ajax
    {
        public partial class Index : AjaxPage<Index>
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                
            }
    
            [AjaxMethod]
            public void GetPerson(string id)
            {
               List<Person> ps = new List<Person>();
               ps.Add(new Person
               {
                   Id = "a001",
                   Name = "abc",
                   Sex = "",
                   Age = 20
               });
    
               ps.Add(new Person
               {
                   Id = "a002",
                   Name = "xyz",
                   Sex = "",
                   Age = 18
               });
    
               ps.Add(new Person
               {
                   Id = "a003",
                   Name = "zzzz",
                   Sex = "",
                   Age = 28
               });
    
               ps.Add(new Person
               {
                   Id = "a004",
                   Name = "yyy",
                   Sex = "",
                   Age = 21
               });
    
               StringBuilder builder = new StringBuilder();
               Person person = ps.Find(p => p.Id == id);
               if (person != null)
               {
                   //http://htmltextwriterutil.codeplex.com/ 这是htmltextwriter工具的下载地址,一款拼字符串的好工具
                   builder.Append("   <ul>");
                   builder.AppendFormat("      <li>编号:{0}</li>",person.Id);
                   builder.AppendFormat("      <li>姓名:{0}</li>", person.Name);
                   builder.AppendFormat("      <li>性别:{0}</li>", person.Sex);
                   builder.AppendFormat("      <li>年龄:{0}</li>", person.Age);
                   builder.Append("   </ul>");
               }
    
               HttpContext.Current.Response.Write(builder.ToString());
               HttpContext.Current.Response.End();
            }
        }
    
        
        public class Person
        {
            public string Id { get; set; }
            public string Name { get; set; }
            public string Sex { get; set; }
            public int Age { get; set; }
        }
    }

    这里的使用有两个要点,一是页面要继承自AjaxPage<T>泛型类,第二是在要被客户端调用的方法上加上[AjaxMethod]特性,一切就这么简单。。

    5.客户端调用

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AjaxTest.aspx.cs" Inherits="AjaxInvokeDemo.Ajax.AjaxTest" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <script type="text/javascript" src="../Scripts/jquery-1.4.1.min.js"></script>
        <script type="text/javascript">
          $(function(){
          $("#btn").click(function(){
              $("#box").load("Index.aspx?action=GetPerson&id="+$("#txtId").val());
          });
        });
        </script>
        
    </head>
    <body>
        <form id="form1" runat="server">
        用户ID:<input type="text" id="txtId" value="a001"/><input type="button" id="btn" value="查询"/>
        <div id="box">
        </div>
        </form>
    </body>
    </html>

     至此,调用完毕。。。

    最后,还是附上代码吧。下载网站项目之后里面你会看到一个叫做AJAx的文件夹,里面就是所有代码了,运行AjaxTest.aspx页面就可以直接体验效果了。文章写的比较匆忙,如果你有任何疑问或建议都请告诉我。。。好啦,就到这里吧

    文件下载:下载

  • 相关阅读:
    Python装饰器的解包装(unwrap)
    《Python cookbook》 “定义一个属性可由用户修改的装饰器” 笔记
    关于Python的函数(Method)与方法(Function)
    判断python对象是否可调用的三种方式及其区别
    tornado返回指定的http code
    Mac下安装pymssql
    iptables
    OpenFlow通信流程解读
    Prometheus的架构及持久化
    ansible总结
  • 原文地址:https://www.cnblogs.com/huangzelin/p/2656814.html
Copyright © 2011-2022 走看看