微信开发:使用反射+虚函数的方式分散处理微信不同消息类型
电脑版发表于:2019/1/18 10:11
微信只会向我们一个地方推送消息,如果全部逻辑都写到一起,代码会非常多。
所以我们可以考虑通过消息类型,来实现不同的消息类型调用不同的处理方法,分散处理,降低代码的耦合性。
先定义一个用于处理请求的基类
public class BaseProcess { protected string ToUserName = ""; protected string FromUserName = ""; protected string MsgType = ""; /// <summary> /// 解析公共参数的方法 /// </summary> /// <param name="root"></param> public void DealCommonParameter(XElement root) { ToUserName = root.Element("ToUserName").Value; FromUserName = root.Element("FromUserName").Value; MsgType = root.Element("MsgType").Value; } /// <summary> /// 处理微信消息的虚函数 /// </summary> /// <param name="root"></param> /// <param name="Response"></param> public virtual void Process(XElement root, HttpResponseBase Response) { } }
然后不同的处理方法都去实现这个基类
例如:处理事件请求的处理方法 (消息类型为event)
public class EventProcess : BaseProcess { public override void Process(XElement root, HttpResponseBase Response) { string Event = root.Element("Event").Value; if (Event == "CLICK") { string EventKey = root.Element("EventKey").Value; if (EventKey == "wx_menu_net") { Response.Write(WXTools.SendNewsMsg(ToUserName, FromUserName)); Response.End(); } else if (EventKey == "wx_menu_python") { Response.Write(WXTools.SendTextMsg(ToUserName, FromUserName, "你点击了python")); Response.End(); } else { Response.Write(WXTools.SendTextMsg(ToUserName, FromUserName, "你点击了事件")); Response.End(); } } } }
又如:处理用户发送的文本消息方法(消息类型为text) :
/// <summary> /// 处理文本消息 /// </summary> public class TextProcess : BaseProcess { public override void Process(XElement root, HttpResponseBase Response) { string content = root.Element("Content").Value; //关键字回复 if (content.Contains("姐姐")) { Response.Write(WXTools.SendImgMsg(ToUserName, FromUserName, "q6yc_ZO")); Response.End(); } if (content.Contains("视频") || content.Contains("教程") || content.Contains("微信")) { Response.Write(WXTools.SendVedioMsg(ToUserName, FromUserName, "q6yc_ZOszJbRSKad74", "视频教程", "这是一个微信开发视频教程")); Response.End(); } if (content.Contains("图文")) { Response.Write(WXTools.SendNewsMsg(ToUserName, FromUserName)); Response.End(); } else { //记录一下日志 LogTools.WriteLog(content, "接收到文本消息"); Response.Write(WXTools.SendTextMsg(ToUserName, FromUserName, content)); Response.End(); } } }
在如处理图片消息的类:
public class ImageProcess : BaseProcess { public override void Process(XElement root, HttpResponseBase Response) { string MediaId = root.Element("MediaId").Value; //记录一下日志 //LogTools.WriteLog(PicUrl, "接收到图片消息"); Response.Write(WXTools.SendImgMsg(ToUserName, FromUserName, MediaId)); Response.End(); } }
结构如图:
然后在入口点用反射处理下就行了 :
/// <summary> /// 微信推送统一入口 /// </summary> public void Index() { //获取微信推送的内容 StreamReader reader = new StreamReader(Request.InputStream); string xml = reader.ReadToEnd(); if (string.IsNullOrEmpty(xml)) { return; } //解析xml,获取xml里边的具体值 XElement root = XElement.Parse(xml); //首字母转大写 string MsgType = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(root.Element("MsgType").Value); //根据不同的消息类型,通过反射去找到不同类的处理方法 //反射创建对象 object obj = Activator.CreateInstance(Type.GetType("MvcApplication2.Process." + MsgType + "Process")); //父类提供公共参数 obj.GetType().GetMethod("DealCommonParamter").Invoke(obj, new object[] { root }); //调用具体的处理方法 obj.GetType().GetMethod("Process").Invoke(obj, new object[] { root, Response }); }
当然公共参数的处理也可以直接封装到一个对象,然后反射调用方法的时候多传一个即可。