Replaces a bunch of dictionary operations with indexing into an array by
doing some caching. Also eliminating an enumerator allocation by changing
from IReadOnlyDictionary to RouteValueDictionary.
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.
This change removes the call to string.Split and a few substrings, and
replaces it with a tokenizer API. The tokenizer isn't really optimized
right now for compute - it should probably be an iterator- but it's a
significant improvement on what we're doing.
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 makes RouteValueDictionary a full IDictionary implementation
instead of a subclass of Dictionary.
Followed the patterns used in the old implementation, namely preserving
the struct-returning behavior of Keys/Values/GetEnumerator.