Skip to content

Commit fa0cb71

Browse files
authored
Make the default route constraints linkable (#24727)
- Added a helper that gives the linker the ability to preserve the constructors of these types
1 parent 983e7ed commit fa0cb71

File tree

2 files changed

+42
-32
lines changed

2 files changed

+42
-32
lines changed

src/Http/Routing/src/ParameterPolicyActivator.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using System;
77
using System.Collections.Generic;
8+
using System.Diagnostics.CodeAnalysis;
89
using System.Globalization;
910
using System.Linq;
1011
using System.Reflection;
@@ -86,6 +87,7 @@ public static T ResolveParameterPolicy<T>(
8687
}
8788
}
8889

90+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern", Justification = "This type comes from the ConstraintMap.")]
8991
private static IParameterPolicy CreateParameterPolicy(IServiceProvider serviceProvider, Type parameterPolicyType, string argumentString)
9092
{
9193
ConstructorInfo activationConstructor = null;

src/Http/Routing/src/RouteOptions.cs

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Diagnostics;
7+
using System.Diagnostics.CodeAnalysis;
78
using Microsoft.AspNetCore.Routing.Constraints;
89

910
namespace Microsoft.AspNetCore.Routing
@@ -82,38 +83,45 @@ public IDictionary<string, Type> ConstraintMap
8283

8384
private static IDictionary<string, Type> GetDefaultConstraintMap()
8485
{
85-
return new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase)
86-
{
87-
// Type-specific constraints
88-
{ "int", typeof(IntRouteConstraint) },
89-
{ "bool", typeof(BoolRouteConstraint) },
90-
{ "datetime", typeof(DateTimeRouteConstraint) },
91-
{ "decimal", typeof(DecimalRouteConstraint) },
92-
{ "double", typeof(DoubleRouteConstraint) },
93-
{ "float", typeof(FloatRouteConstraint) },
94-
{ "guid", typeof(GuidRouteConstraint) },
95-
{ "long", typeof(LongRouteConstraint) },
96-
97-
// Length constraints
98-
{ "minlength", typeof(MinLengthRouteConstraint) },
99-
{ "maxlength", typeof(MaxLengthRouteConstraint) },
100-
{ "length", typeof(LengthRouteConstraint) },
101-
102-
// Min/Max value constraints
103-
{ "min", typeof(MinRouteConstraint) },
104-
{ "max", typeof(MaxRouteConstraint) },
105-
{ "range", typeof(RangeRouteConstraint) },
106-
107-
// Regex-based constraints
108-
{ "alpha", typeof(AlphaRouteConstraint) },
109-
{ "regex", typeof(RegexInlineRouteConstraint) },
110-
111-
{"required", typeof(RequiredRouteConstraint) },
112-
113-
// Files
114-
{ "file", typeof(FileNameRouteConstraint) },
115-
{ "nonfile", typeof(NonFileNameRouteConstraint) },
116-
};
86+
var defaults = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
87+
88+
// Type-specific constraints
89+
AddConstraint<IntRouteConstraint>(defaults, "int");
90+
AddConstraint<BoolRouteConstraint>(defaults, "bool");
91+
AddConstraint<DateTimeRouteConstraint>(defaults, "datetime");
92+
AddConstraint<DecimalRouteConstraint>(defaults, "decimal");
93+
AddConstraint<DoubleRouteConstraint>(defaults, "double");
94+
AddConstraint<FloatRouteConstraint>(defaults, "float");
95+
AddConstraint<GuidRouteConstraint>(defaults, "guid");
96+
AddConstraint<LongRouteConstraint>(defaults, "long");
97+
98+
// Length constraints
99+
AddConstraint<MinLengthRouteConstraint>(defaults, "minlength");
100+
AddConstraint<MaxLengthRouteConstraint>(defaults, "maxlength");
101+
AddConstraint<LengthRouteConstraint>(defaults, "length");
102+
103+
// Min/Max value constraints
104+
AddConstraint<MinRouteConstraint>(defaults, "min");
105+
AddConstraint<MaxRouteConstraint>(defaults, "max");
106+
AddConstraint<RangeRouteConstraint>(defaults, "range");
107+
108+
// Regex-based constraints
109+
AddConstraint<AlphaRouteConstraint>(defaults, "alpha");
110+
AddConstraint<RegexInlineRouteConstraint>(defaults, "regex");
111+
112+
AddConstraint<RequiredRouteConstraint>(defaults, "required");
113+
114+
// Files
115+
AddConstraint<FileNameRouteConstraint>(defaults, "file");
116+
AddConstraint<NonFileNameRouteConstraint>(defaults, "nonfile");
117+
118+
return defaults;
119+
}
120+
121+
// This API could be exposed on RouteOptions
122+
private static void AddConstraint<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]TConstraint>(Dictionary<string, Type> constraintMap, string text) where TConstraint : IRouteConstraint
123+
{
124+
constraintMap[text] = typeof(TConstraint);
117125
}
118126
}
119127
}

0 commit comments

Comments
 (0)