Skip to content

Commit f3836ae

Browse files
authored
Refactor RoutePatternFactory to trim regex dependency where possible (#46793)
1 parent 86e3a4b commit f3836ae

File tree

1 file changed

+65
-56
lines changed

1 file changed

+65
-56
lines changed

src/Http/Routing/src/Patterns/RoutePatternFactory.cs

Lines changed: 65 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public static RoutePattern Parse([StringSyntax("Route")] string pattern, object?
5858
ArgumentNullException.ThrowIfNull(pattern);
5959

6060
var original = RoutePatternParser.Parse(pattern);
61-
return PatternCore(original.RawText, Wrap(defaults), Wrap(parameterPolicies), requiredValues: null, original.PathSegments);
61+
return PatternCore(original.RawText, Wrap(defaults), CreateRoutePatternPolicyReferences(Wrap(parameterPolicies)), requiredValues: null, original.PathSegments);
6262
}
6363

6464
/// <summary>
@@ -83,7 +83,7 @@ public static RoutePattern Parse([StringSyntax("Route")] string pattern, RouteVa
8383
ArgumentNullException.ThrowIfNull(pattern);
8484

8585
var original = RoutePatternParser.Parse(pattern);
86-
return PatternCore(original.RawText, defaults, parameterPolicies, requiredValues: null, original.PathSegments);
86+
return PatternCore(original.RawText, defaults, CreateRoutePatternPolicyReferences(parameterPolicies), requiredValues: null, original.PathSegments);
8787
}
8888

8989
/// <summary>
@@ -112,7 +112,7 @@ public static RoutePattern Parse([StringSyntax("Route")] string pattern, object?
112112
ArgumentNullException.ThrowIfNull(pattern);
113113

114114
var original = RoutePatternParser.Parse(pattern);
115-
return PatternCore(original.RawText, Wrap(defaults), Wrap(parameterPolicies), Wrap(requiredValues), original.PathSegments);
115+
return PatternCore(original.RawText, Wrap(defaults), CreateRoutePatternPolicyReferences(Wrap(parameterPolicies)), Wrap(requiredValues), original.PathSegments);
116116
}
117117

118118
/// <summary>
@@ -140,7 +140,7 @@ public static RoutePattern Parse([StringSyntax("Route")] string pattern, RouteVa
140140
ArgumentNullException.ThrowIfNull(pattern);
141141

142142
var original = RoutePatternParser.Parse(pattern);
143-
return PatternCore(original.RawText, defaults, parameterPolicies, requiredValues, original.PathSegments);
143+
return PatternCore(original.RawText, defaults, CreateRoutePatternPolicyReferences(parameterPolicies), requiredValues, original.PathSegments);
144144
}
145145

146146
/// <summary>
@@ -193,7 +193,7 @@ public static RoutePattern Pattern(
193193
{
194194
ArgumentNullException.ThrowIfNull(segments);
195195

196-
return PatternCore(null, new RouteValueDictionary(defaults), new RouteValueDictionary(parameterPolicies), requiredValues: null, segments);
196+
return PatternCore(null, Wrap(defaults), CreateRoutePatternPolicyReferences(Wrap(parameterPolicies)), requiredValues: null, segments);
197197
}
198198

199199
/// <summary>
@@ -220,7 +220,7 @@ public static RoutePattern Pattern(
220220
{
221221
ArgumentNullException.ThrowIfNull(segments);
222222

223-
return PatternCore(null, defaults, parameterPolicies, requiredValues: null, segments);
223+
return PatternCore(null, defaults, CreateRoutePatternPolicyReferences(parameterPolicies), requiredValues: null, segments);
224224
}
225225

226226
/// <summary>
@@ -250,7 +250,7 @@ public static RoutePattern Pattern(
250250
{
251251
ArgumentNullException.ThrowIfNull(segments);
252252

253-
return PatternCore(rawText, new RouteValueDictionary(defaults), new RouteValueDictionary(parameterPolicies), requiredValues: null, segments);
253+
return PatternCore(rawText, Wrap(defaults), CreateRoutePatternPolicyReferences(Wrap(parameterPolicies)), requiredValues: null, segments);
254254
}
255255

256256
/// <summary>
@@ -279,7 +279,7 @@ public static RoutePattern Pattern(
279279
{
280280
ArgumentNullException.ThrowIfNull(segments);
281281

282-
return PatternCore(rawText, defaults, parameterPolicies, requiredValues: null, segments);
282+
return PatternCore(rawText, defaults, CreateRoutePatternPolicyReferences(parameterPolicies), requiredValues: null, segments);
283283
}
284284

285285
/// <summary>
@@ -332,7 +332,7 @@ public static RoutePattern Pattern(
332332
{
333333
ArgumentNullException.ThrowIfNull(segments);
334334

335-
return PatternCore(null, new RouteValueDictionary(defaults), new RouteValueDictionary(parameterPolicies), requiredValues: null, segments);
335+
return PatternCore(null, Wrap(defaults), CreateRoutePatternPolicyReferences(Wrap(parameterPolicies)), requiredValues: null, segments);
336336
}
337337

338338
/// <summary>
@@ -359,7 +359,7 @@ public static RoutePattern Pattern(
359359
{
360360
ArgumentNullException.ThrowIfNull(segments);
361361

362-
return PatternCore(null, defaults, parameterPolicies, requiredValues: null, segments);
362+
return PatternCore(null, defaults, CreateRoutePatternPolicyReferences(parameterPolicies), requiredValues: null, segments);
363363
}
364364

365365
/// <summary>
@@ -389,7 +389,7 @@ public static RoutePattern Pattern(
389389
{
390390
ArgumentNullException.ThrowIfNull(segments);
391391

392-
return PatternCore(rawText, new RouteValueDictionary(defaults), new RouteValueDictionary(parameterPolicies), requiredValues: null, segments);
392+
return PatternCore(rawText, Wrap(defaults), CreateRoutePatternPolicyReferences(Wrap(parameterPolicies)), requiredValues: null, segments);
393393
}
394394

395395
/// <summary>
@@ -418,13 +418,13 @@ public static RoutePattern Pattern(
418418
{
419419
ArgumentNullException.ThrowIfNull(segments);
420420

421-
return PatternCore(rawText, defaults, parameterPolicies, requiredValues: null, segments);
421+
return PatternCore(rawText, defaults, CreateRoutePatternPolicyReferences(parameterPolicies), requiredValues: null, segments);
422422
}
423423

424424
private static RoutePattern PatternCore(
425425
string? rawText,
426426
RouteValueDictionary? defaults,
427-
RouteValueDictionary? parameterPolicies,
427+
Dictionary<string, List<RoutePatternParameterPolicyReference>>? parameterPolicyReferences,
428428
RouteValueDictionary? requiredValues,
429429
IEnumerable<RoutePatternPathSegment> segments)
430430
{
@@ -450,43 +450,6 @@ private static RoutePattern PatternCore(
450450
}
451451
}
452452

453-
Dictionary<string, List<RoutePatternParameterPolicyReference>>? updatedParameterPolicies = null;
454-
if (parameterPolicies != null && parameterPolicies.Count > 0)
455-
{
456-
updatedParameterPolicies = new Dictionary<string, List<RoutePatternParameterPolicyReference>>(parameterPolicies.Count, StringComparer.OrdinalIgnoreCase);
457-
458-
foreach (var kvp in parameterPolicies)
459-
{
460-
var policyReferences = new List<RoutePatternParameterPolicyReference>();
461-
462-
if (kvp.Value is IParameterPolicy parameterPolicy)
463-
{
464-
policyReferences.Add(ParameterPolicy(parameterPolicy));
465-
}
466-
else if (kvp.Value is string)
467-
{
468-
// Constraint will convert string values into regex constraints
469-
policyReferences.Add(Constraint(kvp.Value));
470-
}
471-
else if (kvp.Value is IEnumerable multiplePolicies)
472-
{
473-
foreach (var item in multiplePolicies)
474-
{
475-
// Constraint will convert string values into regex constraints
476-
policyReferences.Add(item is IParameterPolicy p ? ParameterPolicy(p) : Constraint(item));
477-
}
478-
}
479-
else
480-
{
481-
throw new InvalidOperationException(Resources.FormatRoutePattern_InvalidConstraintReference(
482-
kvp.Value ?? "null",
483-
typeof(IRouteConstraint)));
484-
}
485-
486-
updatedParameterPolicies.Add(kvp.Key, policyReferences);
487-
}
488-
}
489-
490453
List<RoutePatternParameterPart>? parameters = null;
491454
var updatedSegments = segments.ToArray();
492455
for (var i = 0; i < updatedSegments.Length; i++)
@@ -554,8 +517,8 @@ private static RoutePattern PatternCore(
554517
return new RoutePattern(
555518
rawText,
556519
updatedDefaults ?? EmptyDictionary,
557-
updatedParameterPolicies != null
558-
? updatedParameterPolicies.ToDictionary(kvp => kvp.Key, kvp => (IReadOnlyList<RoutePatternParameterPolicyReference>)kvp.Value.ToArray())
520+
parameterPolicyReferences != null
521+
? parameterPolicyReferences.ToDictionary(kvp => kvp.Key, kvp => (IReadOnlyList<RoutePatternParameterPolicyReference>)kvp.Value.ToArray())
559522
: EmptyPoliciesDictionary,
560523
requiredValues ?? EmptyDictionary,
561524
(IReadOnlyList<RoutePatternParameterPart>?)parameters ?? Array.Empty<RoutePatternParameterPart>(),
@@ -627,16 +590,16 @@ RoutePatternPart VisitPart(RoutePatternPart part)
627590
}
628591

629592
List<RoutePatternParameterPolicyReference>? parameterConstraints = null;
630-
if ((updatedParameterPolicies == null || !updatedParameterPolicies.TryGetValue(parameter.Name, out parameterConstraints)) &&
593+
if ((parameterPolicyReferences == null || !parameterPolicyReferences.TryGetValue(parameter.Name, out parameterConstraints)) &&
631594
parameter.ParameterPolicies.Count > 0)
632595
{
633-
if (updatedParameterPolicies == null)
596+
if (parameterPolicyReferences == null)
634597
{
635-
updatedParameterPolicies = new Dictionary<string, List<RoutePatternParameterPolicyReference>>(StringComparer.OrdinalIgnoreCase);
598+
parameterPolicyReferences = new Dictionary<string, List<RoutePatternParameterPolicyReference>>(StringComparer.OrdinalIgnoreCase);
636599
}
637600

638601
parameterConstraints = new List<RoutePatternParameterPolicyReference>(parameter.ParameterPolicies.Count);
639-
updatedParameterPolicies.Add(parameter.Name, parameterConstraints);
602+
parameterPolicyReferences.Add(parameter.Name, parameterConstraints);
640603
}
641604

642605
if (parameter.ParameterPolicies.Count > 0)
@@ -661,6 +624,52 @@ RoutePatternPart VisitPart(RoutePatternPart part)
661624
}
662625
}
663626

627+
/// <summary>
628+
/// String policy references are infered to be regex constraints. Creating them is moved here to its own method so apps can
629+
/// trim away the regex dependency when RoutePatternFactory.Parse(string) is used. This is the method typically used by the various Map methods.
630+
/// </summary>
631+
private static Dictionary<string, List<RoutePatternParameterPolicyReference>>? CreateRoutePatternPolicyReferences(RouteValueDictionary? parameterPolicies)
632+
{
633+
Dictionary<string, List<RoutePatternParameterPolicyReference>>? updatedParameterPolicies = null;
634+
if (parameterPolicies != null && parameterPolicies.Count > 0)
635+
{
636+
updatedParameterPolicies = new Dictionary<string, List<RoutePatternParameterPolicyReference>>(parameterPolicies.Count, StringComparer.OrdinalIgnoreCase);
637+
638+
foreach (var kvp in parameterPolicies)
639+
{
640+
var policyReferences = new List<RoutePatternParameterPolicyReference>();
641+
642+
if (kvp.Value is IParameterPolicy parameterPolicy)
643+
{
644+
policyReferences.Add(ParameterPolicy(parameterPolicy));
645+
}
646+
else if (kvp.Value is string)
647+
{
648+
// Constraint will convert string values into regex constraints
649+
policyReferences.Add(Constraint(kvp.Value));
650+
}
651+
else if (kvp.Value is IEnumerable multiplePolicies)
652+
{
653+
foreach (var item in multiplePolicies)
654+
{
655+
// Constraint will convert string values into regex constraints
656+
policyReferences.Add(item is IParameterPolicy p ? ParameterPolicy(p) : Constraint(item));
657+
}
658+
}
659+
else
660+
{
661+
throw new InvalidOperationException(Resources.FormatRoutePattern_InvalidConstraintReference(
662+
kvp.Value ?? "null",
663+
typeof(IRouteConstraint)));
664+
}
665+
666+
updatedParameterPolicies.Add(kvp.Key, policyReferences);
667+
}
668+
}
669+
670+
return updatedParameterPolicies;
671+
}
672+
664673
/// <summary>
665674
/// Creates a <see cref="RoutePatternPathSegment"/> from the provided collection
666675
/// of parts.

0 commit comments

Comments
 (0)