/// <summary>
        /// 根据要调用的方法名返回对应的 Action
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="action"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        private static ActionDescription GetServiceAction(Type controller, string action, HttpRequest request)
        {
            if (controller == null)
            {
                throw new ArgumentNullException("controller");
            }
            if (string.IsNullOrEmpty(action))
            {
                throw new ArgumentNullException("action");
            }

            // 首先尝试从缓存中读取
            string            key = request.HttpMethod + "#" + controller.FullName + "@" + action;
            ActionDescription mi  = (ActionDescription)s_ServiceActionTable[key];

            if (mi == null)
            {
                bool saveToCache = true;

                MethodInfo method = FindAction(action, controller, request);

                if (method == null)
                {
                    // 如果Action的名字是submit并且是POST提交,则需要自动寻找Action
                    // 例如:多个提交都采用一样的方式:POST /Ajax/Product/submit
                    if (action.IsSame("submit") && request.HttpMethod.IsSame("POST"))
                    {
                        // 自动寻找Action
                        method      = FindSubmitAction(controller, request);
                        saveToCache = false;
                    }
                }

                if (method == null)
                {
                    return(null);
                }

                var attr = method.GetMyAttribute <ActionAttribute>();
                mi = new ActionDescription(method, attr);

                if (saveToCache)
                {
                    s_ServiceActionTable[key] = mi;
                }
            }

            return(mi);
        }
        /// <summary>
        /// 根据一个页面请求路径,返回内部表示的调用信息。
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static InvokeInfo GetActionInvokeInfo(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }

            MatchActionDescription md     = null;
            ActionDescription      action = null;

            // 先直接用URL从字典中查找匹配项。
            if (s_PageActionDict.TryGetValue(url, out action) == false)
            {
                // 如果不能直接匹配URL,就用正则表达式再逐个匹配。
                md = GetActionUsingRegex(url);
                if (md == null)
                {
                    return(null);
                }
                else
                {
                    action = md.ActionDescription;
                }
            }

            InvokeInfo vkInfo = new InvokeInfo();

            vkInfo.Controller = action.PageController;
            vkInfo.Action     = action;

            if (md != null)
            {
                vkInfo.RegexMatch = md.Match;
            }

            if (vkInfo.Action.MethodInfo.IsStatic == false)
            {
                //vkInfo.Instance = Activator.CreateInstance(vkInfo.Controller.ControllerType);
                vkInfo.Instance = vkInfo.Controller.ControllerType.FastNew();
            }

            return(vkInfo);
        }
        /// <summary>
        /// 加载所有的Controller
        /// </summary>
        private static void InitControllers()
        {
            BaseActionHandlerFactory[] baseActionHandlerFactoryList = GetConfigBaseActionHandlerFactory();

            List <ControllerDescription> serviceControllerList = new List <ControllerDescription>(1024);
            var pageControllerList = new List <ControllerDescription>(1024);

            ICollection assemblies = BuildManager.GetReferencedAssemblies();

            foreach (Assembly assembly in assemblies)
            {
                // 过滤以【System】开头的程序集,加快速度
                if (assembly.FullName.StartsWith("System", StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                foreach (Type t in assembly.GetExportedTypes())
                {
                    if (t.IsClass == false)
                    {
                        continue;
                    }

                    if (t.Name.EndsWith("Controller"))
                    {
                        pageControllerList.Add(new ControllerDescription(t));
                    }

                    for (int i = 0; i < baseActionHandlerFactoryList.Length; i++)
                    {
                        if (baseActionHandlerFactoryList[i].TypeIsService(t))
                        {
                            serviceControllerList.Add(new ControllerDescription(t));
                            break;
                        }
                    }
                }
            }

            // 用于Ajax or Service 调用的Action信息则采用延迟加载的方式。

            s_ServiceFullNameDict = serviceControllerList.ToDictionary(x => x.ControllerType.FullName, StringComparer.OrdinalIgnoreCase);

            s_ServiceShortNameDict = new Dictionary <string, ControllerDescription>(s_ServiceFullNameDict.Count, StringComparer.OrdinalIgnoreCase);

            foreach (ControllerDescription description in serviceControllerList)
            {
                try {
                    s_ServiceShortNameDict.Add(description.ControllerType.Name, description);
                }
                catch (ArgumentException) {
                    // 如果遇到已存在的KEY,把原先存放的项也设置为 null,便于查找时返回 null
                    // 也就是说:短名不能重复,如果重复则不返回任何一个。
                    s_ServiceShortNameDict[description.ControllerType.Name] = null;
                }
            }



            // 提前加载Page Controller中的所有Action方法
            s_PageActionDict = new Dictionary <string, ActionDescription>(4096, StringComparer.OrdinalIgnoreCase);

            List <RegexActionDescription> regexActions = new List <RegexActionDescription>();


            foreach (ControllerDescription controller in pageControllerList)
            {
                foreach (MethodInfo m in controller.ControllerType.GetMethods(ActionBindingFlags))
                {
                    ActionAttribute actionAttr = m.GetMyAttribute <ActionAttribute>();
                    if (actionAttr != null)
                    {
                        ActionDescription actionDescription =
                            new ActionDescription(m, actionAttr)
                        {
                            PageController = controller
                        };

                        PageUrlAttribute[] pageUrlAttrs = m.GetMyAttributes <PageUrlAttribute>();

                        foreach (PageUrlAttribute attr in pageUrlAttrs)
                        {
                            if (string.IsNullOrEmpty(attr.Url) == false)
                            {
                                s_PageActionDict.Add(attr.Url, actionDescription);
                            }
                        }



                        PageRegexUrlAttribute[] regexAttrs = m.GetMyAttributes <PageRegexUrlAttribute>();
                        foreach (PageUrlAttribute attr2 in regexAttrs)
                        {
                            if (string.IsNullOrEmpty(attr2.Url) == false)
                            {
                                Regex regex = new Regex(attr2.Url, RegexOptions.Compiled);
                                regexActions.Add(new RegexActionDescription {
                                    Regex = regex, ActionDescription = actionDescription
                                });
                            }
                        }
                    }
                }
            }


            if (regexActions.Count > 0)
            {
                s_RegPageActionArray = regexActions.ToArray();
            }
        }