public override IParameterPolicy Create(RoutePatternParameterPart parameter, string inlineText) { if (inlineText == null) { throw new ArgumentNullException(nameof(inlineText)); } var parameterPolicy = ParameterPolicyActivator.ResolveParameterPolicy <IParameterPolicy>( _options.ConstraintMap, _serviceProvider, inlineText, out var parameterPolicyKey); if (parameterPolicy == null) { throw new InvalidOperationException($"The constraint reference '{parameterPolicyKey}' could not be resolved to a type. Register the constraint type with '{typeof(RouteOptions)}.{nameof(RouteOptions.ConstraintMap)}'."); } if (parameterPolicy is IRouteConstraint constraint) { return(InitializeRouteConstraint(parameter?.IsOptional ?? false, constraint)); } return(parameterPolicy); }
public override IParameterPolicy Create(RoutePatternParameterPart parameter, string inlineText) { if (inlineText == null) { throw new ArgumentNullException(nameof(inlineText)); } var parameterPolicy = ParameterPolicyActivator.ResolveParameterPolicy <IParameterPolicy>( _options.ConstraintMap, _serviceProvider, inlineText, out var parameterPolicyKey); if (parameterPolicy == null) { throw new InvalidOperationException(Resources.FormatRoutePattern_ConstraintReferenceNotFound( parameterPolicyKey, typeof(RouteOptions), nameof(RouteOptions.ConstraintMap))); } if (parameterPolicy is IRouteConstraint constraint) { return(InitializeRouteConstraint(parameter?.IsOptional ?? false, constraint)); } return(parameterPolicy); }
public MatchProcessor Create(RoutePatternParameterPart parameter, RoutePatternConstraintReference reference) { if (reference == null) { throw new ArgumentNullException(nameof(reference)); } Debug.Assert(reference.MatchProcessor != null || reference.Constraint != null || reference.Content != null); if (reference.MatchProcessor != null) { return(Create(parameter?.Name, reference.MatchProcessor, parameter?.IsOptional ?? false)); } if (reference.Constraint != null) { return(Create(parameter?.Name, reference.Constraint, parameter?.IsOptional ?? false)); } if (reference.Content != null) { return(Create(parameter?.Name, reference.Content, parameter?.IsOptional ?? false)); } // Unreachable throw new NotSupportedException(); }
private bool Equals(RoutePatternParameterPart x, RoutePatternParameterPart y) { return (x.Name == y.Name && x.Default == y.Default && x.ParameterKind == y.ParameterKind && Enumerable.SequenceEqual(x.ParameterPolicies, y.ParameterPolicies, this)); }
private static string BuildRoutePart(RoutePatternPart part) { return(part switch { RoutePatternLiteralPart lit => lit.Content, RoutePatternParameterPart param => $"{{{param.Name}}}", RoutePatternSeparatorPart sep => sep.Content, _ => string.Empty });
public override IParameterPolicy Create(RoutePatternParameterPart parameter, IParameterPolicy parameterPolicy) { if (parameterPolicy == null) { throw new ArgumentNullException(nameof(parameterPolicy)); } if (parameterPolicy is IRouteConstraint routeConstraint) { return(InitializeRouteConstraint(parameter?.IsOptional ?? false, routeConstraint, argument: null)); } return(parameterPolicy); }
public override IParameterPolicy Create(RoutePatternParameterPart parameter, string inlineText) { if (inlineText == null) { throw new ArgumentNullException(nameof(inlineText)); } // Example: // {productId:regex(\d+)} // // ParameterName: productId // value: regex(\d+) // name: regex // argument: \d+ (var name, var argument) = Parse(inlineText); if (!_options.ConstraintMap.TryGetValue(name, out var type)) { throw new InvalidOperationException(Resources.FormatRoutePattern_ConstraintReferenceNotFound( name, typeof(RouteOptions), nameof(RouteOptions.ConstraintMap))); } if (typeof(IRouteConstraint).IsAssignableFrom(type)) { var constraint = DefaultInlineConstraintResolver.CreateConstraint(type, argument); return(InitializeRouteConstraint(parameter?.IsOptional ?? false, constraint, argument)); } if (typeof(IParameterPolicy).IsAssignableFrom(type)) { var parameterPolicy = (IParameterPolicy)_serviceProvider.GetRequiredService(type); return(parameterPolicy); } var message = Resources.FormatRoutePattern_InvalidStringConstraintReference( type, name, typeof(IRouteConstraint), typeof(IParameterPolicy)); throw new InvalidOperationException(message); }
private bool MatchesConstraints(RoutePattern pattern, RoutePatternParameterPart parameter, string key, RouteValueDictionary requiredValues) { if (pattern.ParameterPolicies.TryGetValue(key, out var policies)) { for (var i = 0; i < policies.Count; i++) { var policy = _policyFactory.Create(parameter, policies[i]); if (policy is IRouteConstraint constraint) { if (!constraint.Match(httpContext: null, NullRouter.Instance, key, requiredValues, RouteDirection.IncomingRequest)) { return(false); } } } } return(true); }
/// <summary> /// Creates a parameter policy. /// </summary> /// <param name="parameter">The parameter the parameter policy is being created for.</param> /// <param name="reference">The reference to resolve.</param> /// <returns>The <see cref="IParameterPolicy"/> for the parameter.</returns> public IParameterPolicy Create(RoutePatternParameterPart parameter, RoutePatternParameterPolicyReference reference) { if (reference == null) { throw new ArgumentNullException(nameof(reference)); } Debug.Assert(reference.ParameterPolicy != null || reference.Content != null); if (reference.ParameterPolicy != null) { return(Create(parameter, reference.ParameterPolicy)); } if (reference.Content != null) { return(Create(parameter, reference.Content)); } // Unreachable throw new NotSupportedException(); }
/// <summary> /// Creates a parameter policy. /// </summary> /// <param name="parameter">The parameter the parameter policy is being created for.</param> /// <param name="parameterPolicy">An existing parameter policy.</param> /// <returns>The <see cref="IParameterPolicy"/> for the parameter.</returns> public abstract IParameterPolicy Create(RoutePatternParameterPart parameter, IParameterPolicy parameterPolicy);
private void AddRequiredLiteralValue(RouteEndpoint endpoint, List <DfaNode> nextParents, DfaNode parent, RoutePatternParameterPart parameterPart, object requiredValue) { if (endpoint.RoutePattern.ParameterPolicies.TryGetValue(parameterPart.Name, out var parameterPolicyReferences)) { for (var k = 0; k < parameterPolicyReferences.Count; k++) { var reference = parameterPolicyReferences[k]; var parameterPolicy = _parameterPolicyFactory.Create(parameterPart, reference); if (parameterPolicy is IOutboundParameterTransformer parameterTransformer) { requiredValue = parameterTransformer.TransformOutbound(requiredValue); break; } } } var literalValue = requiredValue?.ToString() ?? throw new InvalidOperationException($"Required value for literal '{parameterPart.Name}' must evaluate to a non-null string."); AddLiteralNode(_includeLabel, nextParents, parent, literalValue); }
private void AddParentsWithMatchingLiteralConstraints(List <DfaNode> nextParents, DfaNode parent, RoutePatternParameterPart parameterPart, IReadOnlyList <RoutePatternParameterPolicyReference> parameterPolicyReferences) { // The list of parameters that fail to meet at least one IParameterLiteralNodeMatchingPolicy. var hasFailingPolicy = parent.Literals.Keys.Count < 32 ? (stackalloc bool[32]).Slice(0, parent.Literals.Keys.Count) : new bool[parent.Literals.Keys.Count]; // Whether or not all parameters have failed to meet at least one constraint. for (var i = 0; i < parameterPolicyReferences.Count; i++) { var reference = parameterPolicyReferences[i]; var parameterPolicy = _parameterPolicyFactory.Create(parameterPart, reference); if (parameterPolicy is IParameterLiteralNodeMatchingPolicy constraint) { var literalIndex = 0; var allFailed = true; foreach (var literal in parent.Literals.Keys) { if (!hasFailingPolicy[literalIndex] && !constraint.MatchesLiteral(parameterPart.Name, literal)) { hasFailingPolicy[literalIndex] = true; } allFailed &= hasFailingPolicy[literalIndex]; literalIndex++; } if (allFailed) { // If we get here it means that all literals have failed at least one policy, which means we can skip checking policies // and return early. This will be a very common case when your constraints are things like "int,length or a regex". return; } } } var k = 0; foreach (var literal in parent.Literals.Values) { if (!hasFailingPolicy[k]) { nextParents.Add(literal); } k++; } }
private void AddParentsMatchingComplexSegment(RouteEndpoint endpoint, List <DfaNode> nextParents, RoutePatternPathSegment segment, DfaNode parent, RoutePatternParameterPart parameterPart) { var routeValues = new RouteValueDictionary(); foreach (var literal in parent.Literals.Keys) { if (RoutePatternMatcher.MatchComplexSegment(segment, literal, routeValues)) { // If we got here (rare) it means that the literal matches the complex segment (for example the literal is something A-B) // there is another thing we can try here, which is to evaluate the policies for the parts in case they have one (for example {a:length(4)}-{b:regex(\d+)}) // so that even if it maps closely to a complex parameter we have a chance to discard it and avoid adding the extra branches. var passedAllPolicies = true; for (var i = 0; i < segment.Parts.Count; i++) { var segmentPart = segment.Parts[i]; if (segmentPart is not RoutePatternParameterPart partParameter) { // We skip over the literals and the separator since we already checked against them continue; } if (!routeValues.TryGetValue(partParameter.Name, out var parameterValue)) { // We have a pattern like {a}-{b}.{part?} and a literal "a-b". Since we've matched the complex segment it means that the optional // parameter was not specified, so we skip it. Debug.Assert(i == segment.Parts.Count - 1 && partParameter.IsOptional); continue; } if (endpoint.RoutePattern.ParameterPolicies.TryGetValue(partParameter.Name, out var parameterPolicyReferences)) { for (var j = 0; j < parameterPolicyReferences.Count; j++) { var reference = parameterPolicyReferences[j]; var parameterPolicy = _parameterPolicyFactory.Create(parameterPart, reference); if (parameterPolicy is IParameterLiteralNodeMatchingPolicy constraint && !constraint.MatchesLiteral(partParameter.Name, (string)parameterValue)) { passedAllPolicies = false; break; } } } } if (passedAllPolicies) { nextParents.Add(parent.Literals[literal]); } } routeValues.Clear(); } }
/// <summary> /// Creates a parameter policy. /// </summary> /// <param name="parameter">The parameter the parameter policy is being created for.</param> /// <param name="inlineText">The inline text to resolve.</param> /// <returns>The <see cref="IParameterPolicy"/> for the parameter.</returns> public abstract IParameterPolicy Create(RoutePatternParameterPart parameter, string inlineText);
private static void RemoveParameterDefault(List <RoutePatternPathSegment> segments, List <RoutePatternParameterPart> parameters, RoutePatternParameterPart parameter) { // We know that a parameter can only appear once, so we only need to rewrite one segment and one parameter. for (var i = 0; i < segments.Count; i++) { var segment = segments[i]; for (var j = 0; j < segment.Parts.Count; j++) { if (object.ReferenceEquals(parameter, segment.Parts[j])) { // Found it! var updatedParameter = RoutePatternFactory.ParameterPart(parameter.Name, @default: null, parameter.ParameterKind, parameter.ParameterPolicies); var updatedParts = new List <RoutePatternPart>(segment.Parts); updatedParts[j] = updatedParameter; segments[i] = RoutePatternFactory.Segment(updatedParts); for (var k = 0; k < parameters.Count; k++) { if (ReferenceEquals(parameter, parameters[k])) { parameters[k] = updatedParameter; break; } } return; } } } }
public override IParameterPolicy Create(RoutePatternParameterPart parameter, string inlineText) { throw new NotImplementedException(); }
public override IParameterPolicy Create(RoutePatternParameterPart parameter, IParameterPolicy parameterPolicy) { throw new NotImplementedException(); }
public string GetResourceId(RouteEndpoint routeEndpoint) { StringBuilder templateBuilder = new StringBuilder(); IEnumerable <RoutePatternPathSegment> pathSegments = routeEndpoint.RoutePattern.PathSegments; if (pathSegments.IsNullOrEmpty()) { return(null); } IDictionary <string, object> values = GetRequiredValues(); foreach (RoutePatternPathSegment segment in pathSegments) { templateBuilder.Append("/"); foreach (RoutePatternPart part in segment.Parts) { if (part.IsLiteral) { RoutePatternLiteralPart literalPart = part as RoutePatternLiteralPart; templateBuilder.Append(literalPart.Content); } else if (part.IsSeparator) { RoutePatternSeparatorPart separatorPart = part as RoutePatternSeparatorPart; templateBuilder.Append(separatorPart.Content); } else { RoutePatternParameterPart parameterPart = part as RoutePatternParameterPart; templateBuilder.Append("{"); if (parameterPart.IsCatchAll) { templateBuilder.Append("*"); if (!parameterPart.EncodeSlashes) { templateBuilder.Append("*"); } } if (values.ContainsKey(parameterPart.Name)) { templateBuilder.Append(values[parameterPart.Name]); } else { templateBuilder.Append(parameterPart.Name); } if (parameterPart.IsOptional) { templateBuilder.Append("?"); } //需不要考虑规则呢? 例如5:int //if (!parameterPart.ParameterPolicies.IsNullOrEmpty()) //{ //} templateBuilder.Append("}"); } } } return(templateBuilder.ToString()); }