private void BuildRules() { if (UrlRule.IndexOf('{') < 0) { KeyAndIsConst.Add(new RuleClass { ConstString = UrlRule }); return; } //约定的规则为 name:rulename或者name:length(最小长度,最大长度)或者name:正则表达式 //n-{name:email} var tempFuncDict =RouteHelper.RouteMatchFuncs; lock (((ICollection)tempFuncDict).SyncRoot) { int start = UrlRule.IndexOf('{'); int end = UrlRule.IndexOf('}'); string tempUrl = UrlRule; _isNullAble = true; while (start >= 0 && end > 0) { if (start > 0) { KeyAndIsConst.Add(new RuleClass { ConstString = tempUrl.Substring(0, start) }); _isNullAble = false; } string temp1 = tempUrl.Substring(start + 1, end - start - 1); tempUrl = tempUrl.Substring(start + temp1.Length + 2).Trim(); //带规则应该用:分隔 //比如{key}不带规则的 if (temp1.IndexOf(':') < 0) { KeyAndIsConst.Add(new RuleClass { ConstString = temp1, IsOnlyKey = true, IsRule = true }); _isNullAble = false; } else { var tempStrs = temp1.Split(':'); var tempRuleClass = new RuleClass { ConstString = tempStrs[0], IsRule = true, RuleKey = tempStrs[1] }; IRouteMatch temp; //直接作为键名 if (tempFuncDict.TryGetValue(tempRuleClass.RuleKey, out temp)) { KeyAndIsConst.Add(tempRuleClass); if (_isNullAble) _isNullAble = temp.IsNullAble; } else { //分开是length和正则的情况 var indexLength = tempRuleClass.RuleKey.IndexOf("length(", StringComparison.Ordinal); if (indexLength >= 0) { var tempLengths = tempRuleClass.RuleKey.Substring(indexLength + 7); int indexLengthEnd = tempLengths.IndexOf(')'); if (indexLengthEnd > 0) tempLengths = tempLengths.Substring(0, indexLengthEnd); var numbers = tempLengths.Split(','); var tempRoute1 = new LengthMatch(numbers[0], numbers.Length > 1 ? numbers[1] : null); tempRuleClass.RuleKey = tempRoute1.GetKeyName; tempFuncDict[tempRoute1.GetKeyName] = tempRoute1; KeyAndIsConst.Add(tempRuleClass); if (_isNullAble) _isNullAble = tempRoute1.IsNullAble; } else { RegexMatch tempRoute; int defaultIndex = tempRuleClass.RuleKey.IndexOf("||", StringComparison.Ordinal); if (defaultIndex > 0) { var regexStr = tempRuleClass.RuleKey.Substring(0, defaultIndex); var defaultStr = tempRuleClass.RuleKey.Substring(defaultIndex + 2); tempRoute = new RegexMatch(regexStr, defaultStr); } else tempRoute = new RegexMatch(tempRuleClass.RuleKey); tempFuncDict[tempRoute.GetKeyName] = tempRoute; tempRuleClass.RuleKey = tempRoute.GetKeyName; KeyAndIsConst.Add(tempRuleClass); if (_isNullAble) _isNullAble = tempRoute.IsNullAble; } } } if (tempUrl.Length == 0) break; _isNullAble = false; start = tempUrl.IndexOf('{'); end = tempUrl.IndexOf('}'); //后面不再带规则 if(start<0) { KeyAndIsConst.Add(new RuleClass { ConstString = tempUrl }); break; } //验证规则 if(start==0) throw new Exception("Url规则设定错误,两个特定路由规则不能连接在一起"); } } }
public static void SetThing(RuleClass <T> rc, T thing) => rc.Thing = thing;
/// <summary> /// 匹配/分隔的Url小片段 /// </summary> /// <param name="urlPart"></param> /// <param name="next"></param> /// <param name="resultRouteData"></param> /// <returns></returns> public bool IsMatch(ref string urlPart, RuleClass next, ref IDictionary<string, object> resultRouteData) { //固定的字符串,不操作路由参数 if (!IsRule) { if (urlPart.Length == 0) return false; if (urlPart.IndexOf(ConstString, StringComparison.OrdinalIgnoreCase) != 0) return false; //如果是最后一个规则 if (next == null) { //固定的字符串长度和urlPart必须一样 return ConstString.Length == urlPart.Length; } //否则处理Url参数准备下一次匹配 urlPart = urlPart.Substring(ConstString.Length); return urlPart.Length > 0; } //是规则,仅作为路由变量的键名 if (IsOnlyKey) { //如果是最后一个规则 if (next == null) { resultRouteData[ConstString] = urlPart; return true; } if (urlPart.Length == 0) return false; //两个规则不能在一起(因为转换时已经检验,此种情况不会发生) //if (next.IsRule) // return false; //根据下一个规则界定边界 int indexStart = urlPart.IndexOf(next.ConstString, StringComparison.OrdinalIgnoreCase); //下一个规则匹配失败 if (indexStart < 0) return false; string tempData = null; if (indexStart == 0) { //跳过这个,如果后面不能匹配,返回false int indexStart1 = urlPart.Substring(next.ConstString.Length).IndexOf(next.ConstString, StringComparison.OrdinalIgnoreCase); if (indexStart1 < 0) return false; tempData = urlPart.Substring(0, next.ConstString.Length + indexStart1); } else tempData = urlPart.Substring(0, indexStart); resultRouteData[ConstString] = tempData; urlPart = urlPart.Substring(tempData.Length); return true; } //不是作为键名,有检验规则 IRouteMatch tempMatch; if (!RouteHelper.RouteMatchFuncs.TryGetValue(RuleKey, out tempMatch)) { throw new Exception("检验规则:" + RuleKey + " 丢失,请检查原因"); } object routeData; //如果是最后一个规则 if (next == null) { if (!tempMatch.Test(urlPart, out routeData)) return false; resultRouteData[ConstString] = routeData; //urlPart = string.Empty; return true; } //否则需要处理Url //两个规则不能在一起(因为转换时已经检验,此种情况不会发生) //if (next.IsRule) // return false; //根据下一个规则界定边界 int indexStart2 = urlPart.IndexOf(next.ConstString, StringComparison.OrdinalIgnoreCase); if (indexStart2 < 0) return false; //获取真正用于匹配的部分 string tempUrlPart = null; if (indexStart2 == 0) { //跳过这个,如果后面不能匹配,返回false int indexStart1 = urlPart.Substring(next.ConstString.Length).IndexOf(next.ConstString, StringComparison.OrdinalIgnoreCase); if (indexStart1 < 0) return false; tempUrlPart = urlPart.Substring(0, next.ConstString.Length + indexStart1); } else tempUrlPart = urlPart.Substring(0, indexStart2); if (!tempMatch.Test(tempUrlPart, out routeData)) return false; resultRouteData[ConstString] = routeData; urlPart = urlPart.Substring(tempUrlPart.Length); return true; }