//<?xml version="1.0" encoding="utf-8"?> //<xml> // <ToUserName><![CDATA[gh_a96a4a619366]]></ToUserName> // <FromUserName><![CDATA[olPjZjsXuQPJoV0HlruZkNzKc91E]]></FromUserName> // <CreateTime>1357986928</CreateTime> // <MsgType><![CDATA[text]]></MsgType> // <Content><![CDATA[中文]]></Content> // <MsgId>5832509444155992350</MsgId> //</xml> /// <summary> /// 获取XDocument转换后的IRequestMessageBase实例。 /// 如果MsgType不存在,抛出UnknownRequestMsgTypeException异常 /// </summary> /// <returns></returns> public static IRequestMessageBase GetRequestEntity(XDocument doc) { RequestMessageBase requestMessage = null; ReceivedMsgType msgType; try { msgType = MessageTypeUtility.GetRequestMsgType(doc); switch (msgType) { case ReceivedMsgType.text: requestMessage = new RequestMessageText(); break; case ReceivedMsgType.location: requestMessage = new RequestMessageLocation(); break; case ReceivedMsgType.image: requestMessage = new RequestMessageImage(); break; case ReceivedMsgType.voice: requestMessage = new RequestMessageVoice(); break; case ReceivedMsgType.video: requestMessage = new RequestMessageVideo(); break; case ReceivedMsgType.link: requestMessage = new RequestMessageLink(); break; case ReceivedMsgType.@event: //判断Event类型 string sEventValue = doc.Root.Element("Event").Value; ReceivedEventType eventValue = (ReceivedEventType)Enum.Parse(typeof(ReceivedEventType), sEventValue, true); switch (eventValue) { case ReceivedEventType.LOCATION: //地理位置 requestMessage = new RequestMessageEventLocation(); break; case ReceivedEventType.subscribe: //订阅(关注) requestMessage = new RequestMessageEventSubscribe(); break; case ReceivedEventType.unsubscribe: //取消订阅(关注) requestMessage = new RequestMessageEventUnsubscribe(); break; case ReceivedEventType.CLICK: //菜单点击 requestMessage = new RequestMessageEventClick(); break; case ReceivedEventType.SCAN: //二维码扫描 requestMessage = new RequestMessageEventScan(); break; case ReceivedEventType.VIEW: //URL跳转 requestMessage = new RequestMessageEventView(); break; default: //其他意外类型(也可以选择抛出异常) throw new NotImplementedException("微信事件为[" + sEventValue + "]的事件未得到处理。请联系系统管理员,谢谢。"); } break; default: throw new NotImplementedException("微信消息类型为[" + msgType.ToString() + "]的消息未得到处理。请联系系统管理员,谢谢。"); } Extensions.FillEntityWithXml(requestMessage, doc); } catch (ArgumentException ex) { throw new WeixinException(string.Format("RequestMessage转换出错!请联系系统管理员,谢谢。\r\n\r\nXML:{0}", doc.ToString()), ex); } return(requestMessage); }
void FilterReceivedData(string s) { if (s.Contains("event")) { string[] splittedParts = s.Split(':'); string eventString = splittedParts[1].Remove(0, 1); switch (eventString) { case "put\n": eventType = ReceivedEventType.Put; break; case "patch\n": eventType = ReceivedEventType.Patch; break; case "keep-alive\n": eventType = ReceivedEventType.KeepAlive; break; } } if (s.Contains("data")) { if (eventType == ReceivedEventType.KeepAlive) { return; } /* TODO THIS PART SHOULD BE IMPROVED WITH BETTER SOLUTION, FOR NOW IT'S WORKING AND DYNAMIC * What are we doing - * 1. Splitting out Path(string) and Data(json) * */ string jsonData = s.Remove(0, 5); string pathString = jsonData.Remove(0, 10).Remove(jsonData.IndexOf("data") - 13, jsonData.Length - jsonData.IndexOf("data") + 3).Remove(0, 1); string dataString = jsonData.Remove(jsonData.Length - 2, 2).Remove(0, jsonData.IndexOf("data") + 6); if (isInitial) { isInitial = false; OnChildEventReceived?.Invoke(new ChildEventArgs(pathString, dataString, true)); var resData = fsJsonParser.Parse(dataString); if (childEventType == ChildEventType.ChildAdded) { GetSnapshot(resData, ""); //store snapshot } return; } switch (eventType) { //TODO Shallow method for all events case ReceivedEventType.Put: //Value Changed Event if (childEventType == ChildEventType.ValueChanged) { if (shallow && pathString.Split('/').Length > 1) { return; } OnChildEventReceived?.Invoke(new ChildEventArgs(pathString, dataString, false)); } //Child Added Event if (childEventType == ChildEventType.ChildAdded) { if (shallow && pathString.Split('/').Length > 1) { return; } if (!CheckCachedChild(pathString)) //make sure that it doesn't exist in snapshot { OnChildEventReceived?.Invoke(new ChildEventArgs(pathString, dataString, false)); AddToSnapshot(pathString, dataString); //add that child to snapshot } } //Child Removed Event if (childEventType == ChildEventType.ChildRemoved && dataString == "null") { if (shallow && pathString.Split('/').Length > 1) { return; } OnChildEventReceived?.Invoke(new ChildEventArgs(pathString, dataString, false)); } //Child Changed Event if (childEventType == ChildEventType.ChildChanged) { if (shallow && pathString.Split('/').Length > 1) { return; } OnChildEventReceived?.Invoke(new ChildEventArgs(pathString, dataString, false)); } break; case ReceivedEventType.Patch: if (childEventType == ChildEventType.ValueChanged) { OnChildEventReceived?.Invoke(new ChildEventArgs(pathString, dataString, false)); } if (childEventType == ChildEventType.ChildChanged) { OnChildEventReceived?.Invoke(new ChildEventArgs(pathString, dataString, false)); } break; case ReceivedEventType.KeepAlive: break; } } void GetSnapshot(fsData data, string path, bool isNested = false) { if (!data.IsDictionary) { return; } var dict = data.AsDictionary; foreach (var key in dict.Keys.ToList()) { if (!shallow && dict[key].IsDictionary) //If any nested child available { string newPath = String.IsNullOrEmpty(path) ? key : path + "/" + key; GetSnapshot(dict[key], newPath, true); } dict[key] = new fsData(""); //makes value null for optimization } //Store in a list, key is node path, value is dictionary of childs, fsData is always empty string nodes.Add(new Dictionary <string, Dictionary <string, fsData> > { { path, dict } }); } void AddToSnapshot(string path, string jsonData) { string[] splittedPath = path.Split('/'); string parentNode = splittedPath.Length > 1 ? path.Replace($"/{splittedPath[splittedPath.Length - 1]}", "") : ""; var targetedDict = new Dictionary <string, fsData>(); foreach (var node in nodes) { foreach (var child in node.Keys.ToList()) { if (child == parentNode) { targetedDict = node[child]; } } } if (targetedDict.Keys.ToList().IndexOf(splittedPath[splittedPath.Length - 1]) == -1) { var fsData = fsJsonParser.Parse(jsonData); if (fsData.IsDictionary) { GetSnapshot(fsData, path); //store snapshot } else { targetedDict.Add(splittedPath[splittedPath.Length - 1], new fsData("")); } } } bool CheckCachedChild(string path) { // nodes is a list of Dictionary. // Each dictionary = each node from initial path // // Each dictionary (node) from list has the following pair- // Key = path from initial path e.g /users // Value = another dictionary of Childs of the following path (/users) // // Dictionary of value has following pair - // Key = child node name e.g srejonkhan. Remember, it's being concatenated with node key. users + "/" + srejonkhan // Value = fsData, contains child data. Eventually turned into a empty string for optimization. // // A node get in depth of database to avoid miscommunication with update child event. // It's better to listen to shallow child foreach (var node in nodes) //Get each node { foreach (var nestedChildNode in node) //get each child node from node dictionary { foreach (var nestedChild in nestedChildNode.Value) //loop through each child { string nodePath = String.IsNullOrEmpty(nestedChildNode.Key) ? nestedChild.Key : nestedChildNode.Key + "/" + nestedChild.Key; if (nodePath == path) { return(true); //Child exists } } } } return(false); } }