//<?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);
        }
Пример #2
0
        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);
            }
        }