This change optimizes allocations by RouteValueDictionary based on usage.
First, implement a struct Enumerator, and expose the concrete RVD type
from all extensibility points. We wanted to try and decouple this code
from RVD originally and use IDictionary everywhere. After doing that we've
found that it allocates an unacceptable number of enumerators.
Secondly, optimize copies of RVD for the case where you're copying an RVC
to another (common case). When doing this we can copy the count to get the
right capacity, and copy the entries without allocating an enumerator.
Lastly, optimize RVD for the case where it's a wrapper around a poco
object. We 'upgrade' to a writable full dictionary if you try to write to
it, or call one of a number of APIs that are uncommonly used. We could
produce optimized versions of things like `Keys` and `CopyTo` if necessary
in the future.
- `DefaultInlineConstraintResolver` has no need of a `IServiceProvider`
nits:
- add doc comments for changed `DefaultInlineConstraintResolver` ctor
- let VS add a dev server port to sample's .kproj
- add debugSettings.json and .vs/ to .gitignore
1. Template parser now allows a parameter to be an optional parameter in a complex segment if
it is the last and only optional parameter and it is followed by a period.
2. Template matcher modified to take into consideration the optional parameter in the complex
segment. Also the period shouldn't be present if the optional parameter is not present
The properties on TemplateRoute for DataTokens and Defaults are now
readonly. This prevents modifying these collections in a way that
invalidates cached data, or violates thread-safety.
To do the same for constraints, this change includes a substantial refactor
of how we realize inline constraints, and moves the constraint resolver
out of the parsing phase.
This allow creates a builder for the constraint map, that will make it
easier to implement features like optional constraints, and is reusable
for anyone building their own type of routing system.
This change adds tests and makes the behavior consistent with legacy MVC
as far as what values are visible in constraints.
This is important because it allows constraints to make decisions based on
whether or not a value is present even if it's not in the template. This
is similar to the behavior of WebAPI link generation or Area link
generation in MVC 5 - but without hardcoding.
We'll need to access the accepted values to do proper link generation, so
separating this process out into 2 parts.
Also moving defaults into the TemplateBinder because they are conceptually
part of the route, not part of the request. I'll do the same for
TemplateMatcher soon, but it's a big change and worth separating.