public static Route Build(RoutePattern pattern, Type handlerType, MethodInfo method) { var inputType = DetermineInputType(method); var hasPrimitives = method.GetParameters().Any(x => x.ParameterType == typeof(string) || RoutingFrames.CanParse(x.ParameterType)); if (hasPrimitives) { for (var i = 0; i < pattern.Segments.Length; i++) { var current = pattern.Segments[i].SegmentPath; var isParameter = current.StartsWith("{") && current.EndsWith("}"); var parameterName = current.TrimStart('{').TrimEnd('}'); var parameter = method.GetParameters().FirstOrDefault(x => x.Name == parameterName); if (parameter != null) { var argument = new RouteArgument(parameter, i); pattern.Segments[i] = argument; } if (isParameter && parameter == null) { throw new InvalidOperationException($"Required parameter '{current}' could not be resoved in method {handlerType.FullNameInCode()}.{method.Name}()"); } } } else if (inputType != null) { var members = inputType.GetProperties().OfType <MemberInfo>().Concat(inputType.GetFields()).ToArray(); for (var i = 0; i < pattern.Segments.Length; i++) { var current = pattern.Segments[i].SegmentPath; var member = members.FirstOrDefault(x => x.Name == current); if (member != null) { var argument = new RouteArgument(member, i); pattern.Segments[i] = argument; } } } var spreads = method.GetParameters().Where(x => x.IsSpread()).ToArray(); if (spreads.Length > 1) { throw new InvalidOperationException( $"An HTTP action method can only take in either '{Route.PathSegments}' or '{Route.RelativePath}', but not both. Error with action {handlerType.FullName}.{method.Name}()"); } var segments = pattern.Segments; if (spreads.Length == 1) { segments = segments.Concat(new ISegment[] { new Spread(segments.Length) }).ToArray(); } var route = new Route(segments, pattern.Method) { HandlerType = handlerType, Method = method, InputType = inputType }; method.ForAttribute <RouteNameAttribute>(att => route.Name = att.Name); return(route); }
public static Route Build(string pattern, Type handlerType, MethodInfo method) { pattern = pattern.Replace("___", "-").Replace("__", "_@"); var parts = pattern.Split('_') .Select(x => x.Replace("@", "_")).ToArray(); var verb = HttpVerbs.All.FirstOrDefault(x => x.EqualsIgnoreCase(parts[0])); if (verb.IsNotEmpty()) { parts = parts.Skip(1).ToArray(); } else { verb = HttpVerbs.GET; } var segments = parts .Select((x, position) => new Segment(x.ToLowerInvariant(), position)) .OfType <ISegment>() .ToArray(); Type inputType = DetermineInputType(method); var hasPrimitives = method.GetParameters().Any(x => x.ParameterType == typeof(Guid) || RouteArgument.Conversions.Has(x.ParameterType)); if (hasPrimitives) { for (var i = 0; i < segments.Length; i++) { var current = parts[i]; var parameter = method.GetParameters().FirstOrDefault(x => x.Name == current); if (parameter != null) { var argument = new RouteArgument(parameter, i); segments[i] = argument; } } } else if (inputType != null) { var members = inputType.GetProperties().OfType <MemberInfo>().Concat(inputType.GetFields()).ToArray(); for (var i = 0; i < segments.Length; i++) { var current = parts[i]; var member = members.FirstOrDefault(x => x.Name == current); if (member != null) { var argument = new RouteArgument(member, i); segments[i] = argument; } } } var route = new Route(segments, verb, env => Task.CompletedTask) { HandlerType = handlerType, Method = method, InputType = inputType }; method.ForAttribute <RouteNameAttribute>(att => route.Name = att.Name); return(route); }
protected bool Equals(RouteArgument other) { return(string.Equals(Key, other.Key) && Position == other.Position); }