internal static RouteHandlerLookupNode BuildRouteHandlerLookupTree(IEnumerable <Type> requestHandlers) { var tree = new RouteHandlerLookupNode(); var knownRouteFragmentSets = new List <IList <string> >(); foreach (var requestHandler in requestHandlers) { var routeAttributes = RequestHandlerDescriptor.GetRouteAttributes(requestHandler); if (routeAttributes.Count == 0) { throw new InvalidOperationException(ExceptionMessageBuilder.BuildMissingRouteMessage(requestHandler)); } var routeHandlerVerb = RequestHandlerDescriptor.GetVerb(requestHandler); var routeFragmentSets = routeAttributes.Select(x => RouteIdentifierBuilder.BuildIdentifier(routeHandlerVerb, x.Template)).ToList(); knownRouteFragmentSets.AddRange(routeFragmentSets); ScanForUnreachableRouteHandlers(knownRouteFragmentSets, routeAttributes.First().Template, requestHandler); ScanForUnreachableRouteParameters(routeFragmentSets, routeAttributes, requestHandler); foreach (var routeFragementSet in routeFragmentSets) { tree.AddNode(routeFragementSet, requestHandler); } } return(tree); }
internal void AddNode(IList <string> routeTemplateFragments, Type requestHandler) { var headFragment = routeTemplateFragments.First(); var remainingTemplateFragments = routeTemplateFragments.Skip(1).ToList(); var childNode = FindChildNode(headFragment); if (childNode != null) { if (remainingTemplateFragments.Any()) { childNode.AddNode(remainingTemplateFragments, requestHandler); } else { childNode.RequestHandler = requestHandler; } } else { var newChildNode = new RouteHandlerLookupNode(headFragment, remainingTemplateFragments, requestHandler); ChildNodes.Add(newChildNode); if (remainingTemplateFragments.Any()) { newChildNode.AddNode(remainingTemplateFragments, requestHandler); } } }
private static bool IsMatch(RouteHandlerLookupNode node, string pathFragment, Dictionary <string, string> routeParameters) { if (node.IsStaticRouteTemplateFragment) { return(node.RouteTemplateFragment.Equals(pathFragment, StringComparison.InvariantCultureIgnoreCase)); } routeParameters.Add(node.RouteTemplateFragment, pathFragment); return(true); }
private static void ScanForUnreachableRouteParameters(IEnumerable <IList <string> > routeFragmentSets, IEnumerable <RouteAttribute> routeAttributes, Type requestHandlerType) { var dynamicRouteFragments = (from routeFragmentSet in routeFragmentSets from fragment in routeFragmentSet where RouteHandlerLookupNode.IsStaticFragment(fragment) == false select RouteHandlerLookupNode.RemoveDynamicFragmentTokens(fragment)).ToList(); if (dynamicRouteFragments.Count == 0) { return; } var propertyNames = requestHandlerType.GetProperties().Select(x => x.Name).ToList(); var unreachableParameter = dynamicRouteFragments.FirstOrDefault(f => propertyNames.Any(n => n.Equals(f, StringComparison.InvariantCultureIgnoreCase)) == false); if (unreachableParameter == null) { return; } throw new InvalidOperationException(ExceptionMessageBuilder.BuildUnreachableRouteParameterMessage(routeAttributes, requestHandlerType, unreachableParameter, propertyNames)); }
private static RouteHandlerLookupResult FindNode(RouteHandlerLookupNode node, IList <string> pathFragments, Dictionary <string, string> routeParameters) { foreach (var childNode in node.ChildNodes) { if (IsMatch(childNode, pathFragments.First(), routeParameters) == false) { continue; } var remainingPathFragments = pathFragments.Skip(1).ToList(); if (remainingPathFragments.Count == 0) { return(new RouteHandlerLookupResult(childNode.RequestHandler, routeParameters)); } var requestHandler = FindNode(childNode, remainingPathFragments, routeParameters); if (requestHandler != null) { return(requestHandler); } } return(RouteHandlerLookupResult.FailedResult); }
public RequestRouter(IEnumerable <Type> requestHandlers) { _tree = RouteHandlerLookupTreeBuilder.BuildRouteHandlerLookupTree(requestHandlers); }