private TemplateBinder CreateTemplateBinder(RouteEndpoint endpoint)
        {
            // Now create the constraints and parameter transformers from the pattern
            var policies = new List <(string parameterName, IParameterPolicy policy)>();

            foreach (var kvp in endpoint.RoutePattern.ParameterPolicies)
            {
                var parameterName = kvp.Key;

                // It's possible that we don't have an actual route parameter, we need to support that case.
                var parameter = endpoint.RoutePattern.GetParameter(parameterName);

                // Use the first parameter transformer per parameter
                var foundTransformer = false;
                for (var i = 0; i < kvp.Value.Count; i++)
                {
                    var parameterPolicy = _parameterPolicyFactory.Create(parameter, kvp.Value[i]);
                    if (!foundTransformer && parameterPolicy is IOutboundParameterTransformer parameterTransformer)
                    {
                        policies.Add((parameterName, parameterTransformer));
                        foundTransformer = true;
                    }

                    if (parameterPolicy is IRouteConstraint constraint)
                    {
                        policies.Add((parameterName, constraint));
                    }
                }
            }

            return(new TemplateBinder(
                       UrlEncoder.Default,
                       _uriBuildingContextPool,
                       endpoint.RoutePattern,
                       new RouteValueDictionary(endpoint.RoutePattern.Defaults),
                       endpoint.RoutePattern.RequiredValues.Keys,
                       policies));
        }
 // Internal for testing
 internal TemplateBinder GetTemplateBinder(RouteEndpoint endpoint) => _cache.EnsureInitialized().GetOrAdd(endpoint, _createTemplateBinder);