Remove Routing pubternal

This change makes a bunch of random routing classes internal instead of
pubternal. Most of these have no use case and aren't valuable at all
outside of routing code.

The one exception here is that the only way to construct a
`TemplateBinder` in 1.0-2.2 is using a constructor that accepts some
pubternal types. I don't think it's a good idea to just yank this since
the usage is pretty wide.

Instead I added a factory service so you can create this, and marked the
constructor [Obsolete] where these types are touched. We can make the
actual breaking change in the next major release.
This commit is contained in:
Ryan Nowak 2019-04-11 16:01:39 -07:00
parent d2db4677c9
commit 763720b092
27 changed files with 276 additions and 135 deletions

View File

@ -491,71 +491,19 @@ namespace Microsoft.AspNetCore.Routing.Constraints
}
namespace Microsoft.AspNetCore.Routing.Internal
{
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct BufferValue
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public BufferValue(string value, bool requiresEncoding) { throw null; }
public bool RequiresEncoding { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public string Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
}
public partial class DfaGraphWriter
{
public DfaGraphWriter(System.IServiceProvider services) { }
public void Write(Microsoft.AspNetCore.Routing.EndpointDataSource dataSource, System.IO.TextWriter writer) { }
}
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplayString,nq}")]
public partial class LinkGenerationDecisionTree
{
public LinkGenerationDecisionTree(System.Collections.Generic.IReadOnlyList<Microsoft.AspNetCore.Routing.Tree.OutboundMatch> entries) { }
public System.Collections.Generic.IList<Microsoft.AspNetCore.Routing.Internal.OutboundMatchResult> GetMatches(Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteValueDictionary ambientValues) { throw null; }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct OutboundMatchResult
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public OutboundMatchResult(Microsoft.AspNetCore.Routing.Tree.OutboundMatch match, bool isFallbackMatch) { throw null; }
public bool IsFallbackMatch { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public Microsoft.AspNetCore.Routing.Tree.OutboundMatch Match { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct PathTokenizer : System.Collections.Generic.IEnumerable<Microsoft.Extensions.Primitives.StringSegment>, System.Collections.Generic.IReadOnlyCollection<Microsoft.Extensions.Primitives.StringSegment>, System.Collections.Generic.IReadOnlyList<Microsoft.Extensions.Primitives.StringSegment>, System.Collections.IEnumerable
{
private object _dummy;
private int _dummyPrimitive;
public PathTokenizer(Microsoft.AspNetCore.Http.PathString path) { throw null; }
public int Count { get { throw null; } }
public Microsoft.Extensions.Primitives.StringSegment this[int index] { get { throw null; } }
public Microsoft.AspNetCore.Routing.Internal.PathTokenizer.Enumerator GetEnumerator() { throw null; }
System.Collections.Generic.IEnumerator<Microsoft.Extensions.Primitives.StringSegment> System.Collections.Generic.IEnumerable<Microsoft.Extensions.Primitives.StringSegment>.GetEnumerator() { throw null; }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct Enumerator : System.Collections.Generic.IEnumerator<Microsoft.Extensions.Primitives.StringSegment>, System.Collections.IEnumerator, System.IDisposable
{
private object _dummy;
private int _dummyPrimitive;
public Enumerator(Microsoft.AspNetCore.Routing.Internal.PathTokenizer tokenizer) { throw null; }
public Microsoft.Extensions.Primitives.StringSegment Current { get { throw null; } }
object System.Collections.IEnumerator.Current { get { throw null; } }
public void Dispose() { }
public bool MoveNext() { throw null; }
public void Reset() { }
}
}
[System.ObsoleteAttribute("This type will be marked as internal in a future release.")]
public enum SegmentState
{
Beginning = 0,
Inside = 1,
}
public partial class UriBuilderContextPooledObjectPolicy : Microsoft.Extensions.ObjectPool.IPooledObjectPolicy<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext>
{
public UriBuilderContextPooledObjectPolicy() { }
public Microsoft.AspNetCore.Routing.Internal.UriBuildingContext Create() { throw null; }
public bool Return(Microsoft.AspNetCore.Routing.Internal.UriBuildingContext obj) { throw null; }
}
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerToString(),nq}")]
[System.ObsoleteAttribute("This type will be marked as internal in a future release.")]
public partial class UriBuildingContext
{
public UriBuildingContext(System.Text.Encodings.Web.UrlEncoder urlEncoder) { }
@ -808,13 +756,21 @@ namespace Microsoft.AspNetCore.Routing.Template
}
public partial class TemplateBinder
{
[System.ObsoleteAttribute("This constructor is obsolete and will be marked internal in a future release. Use the TemplateBinderFactory service to create TemplateBinder instances.")]
public TemplateBinder(System.Text.Encodings.Web.UrlEncoder urlEncoder, Microsoft.Extensions.ObjectPool.ObjectPool<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext> pool, Microsoft.AspNetCore.Routing.Patterns.RoutePattern pattern, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults, System.Collections.Generic.IEnumerable<string> requiredKeys, System.Collections.Generic.IEnumerable<System.ValueTuple<string, Microsoft.AspNetCore.Routing.IParameterPolicy>> parameterPolicies) { }
[System.ObsoleteAttribute("This constructor is obsolete and will be marked internal in a furture release. Use the TemplateBinderFactory service to create TemplateBinder instances.")]
public TemplateBinder(System.Text.Encodings.Web.UrlEncoder urlEncoder, Microsoft.Extensions.ObjectPool.ObjectPool<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext> pool, Microsoft.AspNetCore.Routing.Template.RouteTemplate template, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults) { }
public string BindValues(Microsoft.AspNetCore.Routing.RouteValueDictionary acceptedValues) { throw null; }
public Microsoft.AspNetCore.Routing.Template.TemplateValuesResult GetValues(Microsoft.AspNetCore.Routing.RouteValueDictionary ambientValues, Microsoft.AspNetCore.Routing.RouteValueDictionary values) { throw null; }
public static bool RoutePartsEqual(object a, object b) { throw null; }
public bool TryProcessConstraints(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.RouteValueDictionary combinedValues, out string parameterName, out Microsoft.AspNetCore.Routing.IRouteConstraint constraint) { throw null; }
}
public abstract partial class TemplateBinderFactory
{
protected TemplateBinderFactory() { }
public abstract Microsoft.AspNetCore.Routing.Template.TemplateBinder Create(Microsoft.AspNetCore.Routing.Patterns.RoutePattern pattern);
public abstract Microsoft.AspNetCore.Routing.Template.TemplateBinder Create(Microsoft.AspNetCore.Routing.Template.RouteTemplate template, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults);
}
public partial class TemplateMatcher
{
public TemplateMatcher(Microsoft.AspNetCore.Routing.Template.RouteTemplate template, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults) { }
@ -901,6 +857,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
}
public partial class TreeRouteBuilder
{
[System.ObsoleteAttribute("This constructor will be marked internal in a future release. Use the service provider to create instances of TreeRouteBuilder.")]
public TreeRouteBuilder(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.ObjectPool.ObjectPool<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext> objectPool, Microsoft.AspNetCore.Routing.IInlineConstraintResolver constraintResolver) { }
public System.Collections.Generic.IList<Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry> InboundEntries { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public System.Collections.Generic.IList<Microsoft.AspNetCore.Routing.Tree.OutboundRouteEntry> OutboundEntries { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
@ -913,6 +870,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
public partial class TreeRouter : Microsoft.AspNetCore.Routing.IRouter
{
public static readonly string RouteGroupKey;
[System.ObsoleteAttribute("This constructor will be marked obsolete in a future release. Use the TreeRouterBuilder to create instances of TreeRouter.")]
public TreeRouter(Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree[] trees, System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Routing.Tree.OutboundRouteEntry> linkGenerationEntries, System.Text.Encodings.Web.UrlEncoder urlEncoder, Microsoft.Extensions.ObjectPool.ObjectPool<Microsoft.AspNetCore.Routing.Internal.UriBuildingContext> objectPool, Microsoft.Extensions.Logging.ILogger routeLogger, Microsoft.Extensions.Logging.ILogger constraintLogger, int version) { }
public int Version { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public Microsoft.AspNetCore.Routing.VirtualPathData GetVirtualPath(Microsoft.AspNetCore.Routing.VirtualPathContext context) { throw null; }

View File

@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@ -10,7 +10,7 @@
using System;
using System.Diagnostics;
namespace Microsoft.AspNetCore.Routing.Internal
namespace Microsoft.AspNetCore.Routing
{
/// <summary>
/// Helper type for avoiding allocations while building arrays.
@ -166,4 +166,4 @@ namespace Microsoft.AspNetCore.Routing.Internal
_array = next;
}
}
}
}

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Routing
internal sealed class DefaultLinkGenerator : LinkGenerator, IDisposable
{
private readonly ParameterPolicyFactory _parameterPolicyFactory;
private readonly ObjectPool<UriBuildingContext> _uriBuildingContextPool;
private readonly TemplateBinderFactory _binderFactory;
private readonly ILogger<DefaultLinkGenerator> _logger;
private readonly IServiceProvider _serviceProvider;
@ -38,14 +38,14 @@ namespace Microsoft.AspNetCore.Routing
public DefaultLinkGenerator(
ParameterPolicyFactory parameterPolicyFactory,
TemplateBinderFactory binderFactory,
EndpointDataSource dataSource,
ObjectPool<UriBuildingContext> uriBuildingContextPool,
IOptions<RouteOptions> routeOptions,
ILogger<DefaultLinkGenerator> logger,
IServiceProvider serviceProvider)
{
_parameterPolicyFactory = parameterPolicyFactory;
_uriBuildingContextPool = uriBuildingContextPool;
_binderFactory = binderFactory;
_logger = logger;
_serviceProvider = serviceProvider;
@ -282,40 +282,7 @@ namespace Microsoft.AspNetCore.Routing
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);
return _binderFactory.Create(endpoint.RoutePattern);
}
// Internal for testing

View File

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.AspNetCore.Routing.Template;
using Microsoft.AspNetCore.Routing.Tree;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
@ -34,6 +35,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddTransient<IInlineConstraintResolver, DefaultInlineConstraintResolver>();
services.TryAddTransient<ObjectPoolProvider, DefaultObjectPoolProvider>();
#pragma warning disable CS0618 // Type or member is obsolete
services.TryAddSingleton<ObjectPool<UriBuildingContext>>(s =>
{
var provider = s.GetRequiredService<ObjectPoolProvider>();
@ -49,6 +51,7 @@ namespace Microsoft.Extensions.DependencyInjection
var constraintResolver = s.GetRequiredService<IInlineConstraintResolver>();
return new TreeRouteBuilder(loggerFactory, objectPool, constraintResolver);
}));
#pragma warning restore CS0618 // Type or member is obsolete
services.TryAddSingleton(typeof(RoutingMarkerService));
@ -88,6 +91,7 @@ namespace Microsoft.Extensions.DependencyInjection
//
// Misc infrastructure
//
services.TryAddSingleton<TemplateBinderFactory, DefaultTemplateBinderFactory>();
services.TryAddSingleton<RoutePatternTransformer, DefaultRoutePatternTransformer>();
return services;
}

View File

@ -1,18 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Routing.Internal
{
public readonly struct BufferValue
{
public BufferValue(string value, bool requiresEncoding)
{
Value = value;
RequiresEncoding = requiresEncoding;
}
public bool RequiresEncoding { get; }
public string Value { get; }
}
}

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNetCore.Routing.Internal
{
// Segments are treated as all-or-none. We should never output a partial segment.
@ -9,6 +11,7 @@ namespace Microsoft.AspNetCore.Routing.Internal
// used a value for {p1}, we have to output the entire segment up to the next "/".
// Otherwise we could end up with the partial segment "v1" instead of the entire
// segment "v1-v2.xml".
[Obsolete("This type will be marked as internal in a future release.")]
public enum SegmentState
{
Beginning,

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -10,6 +11,7 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Internal
{
[Obsolete("This type will be marked as internal in a future release.")]
[DebuggerDisplay("{DebuggerToString(),nq}")]
public class UriBuildingContext
{
@ -321,5 +323,18 @@ namespace Microsoft.AspNetCore.Routing.Internal
{
return string.Format("{{Accepted: '{0}' Buffered: '{1}'}}", _path, string.Join("", _buffer));
}
private readonly struct BufferValue
{
public BufferValue(string value, bool requiresEncoding)
{
Value = value;
RequiresEncoding = requiresEncoding;
}
public bool RequiresEncoding { get; }
public string Value { get; }
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@ -9,7 +9,7 @@ using System.Reflection;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Routing.Internal
namespace Microsoft.AspNetCore.Routing
{
internal static class ParameterPolicyActivator
{

View File

@ -8,9 +8,9 @@ using System.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Routing.Internal
namespace Microsoft.AspNetCore.Routing
{
public struct PathTokenizer : IReadOnlyList<StringSegment>
internal struct PathTokenizer : IReadOnlyList<StringSegment>
{
private readonly string _path;
private int _count;

View File

@ -246,14 +246,16 @@ namespace Microsoft.AspNetCore.Routing
}
}
#pragma warning disable CS0618 // Type or member is obsolete
private void EnsureBinder(HttpContext context)
{
if (_binder == null)
{
var pool = context.RequestServices.GetRequiredService<ObjectPool<UriBuildingContext>>();
_binder = new TemplateBinder(UrlEncoder.Default, pool, ParsedTemplate, Defaults);
var binderFactory = context.RequestServices.GetRequiredService<TemplateBinderFactory>();
_binder = binderFactory.Create(ParsedTemplate, Defaults);
}
}
#pragma warning restore CS0618 // Type or member is obsolete
private void EnsureLoggers(HttpContext context)
{

View File

@ -3,7 +3,7 @@
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Routing.Internal
namespace Microsoft.AspNetCore.Routing
{
/// <summary>
/// A marker class used to determine if all the routing services were added
@ -12,4 +12,4 @@ namespace Microsoft.AspNetCore.Routing.Internal
internal class RoutingMarkerService
{
}
}
}

View File

@ -0,0 +1,95 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Routing.Template
{
internal sealed class DefaultTemplateBinderFactory : TemplateBinderFactory
{
private readonly ParameterPolicyFactory _policyFactory;
#pragma warning disable CS0618 // Type or member is obsolete
private readonly ObjectPool<UriBuildingContext> _pool;
#pragma warning restore CS0618 // Type or member is obsolete
public DefaultTemplateBinderFactory(
ParameterPolicyFactory policyFactory,
#pragma warning disable CS0618 // Type or member is obsolete
ObjectPool<UriBuildingContext> pool)
#pragma warning restore CS0618 // Type or member is obsolete
{
if (policyFactory == null)
{
throw new ArgumentNullException(nameof(policyFactory));
}
if (pool == null)
{
throw new ArgumentNullException(nameof(pool));
}
_policyFactory = policyFactory;
_pool = pool;
}
public override TemplateBinder Create(RouteTemplate template, RouteValueDictionary defaults)
{
if (template == null)
{
throw new ArgumentNullException(nameof(template));
}
if (defaults == null)
{
throw new ArgumentNullException(nameof(defaults));
}
#pragma warning disable CS0618 // Type or member is obsolete
return new TemplateBinder(UrlEncoder.Default, _pool, template, defaults);
#pragma warning restore CS0618 // Type or member is obsolete
}
public override TemplateBinder Create(RoutePattern pattern)
{
if (pattern == null)
{
throw new ArgumentNullException(nameof(pattern));
}
// Now create the constraints and parameter transformers from the pattern
var policies = new List<(string parameterName, IParameterPolicy policy)>();
foreach (var kvp in pattern.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 = pattern.GetParameter(parameterName);
// Use the first parameter transformer per parameter
var foundTransformer = false;
for (var i = 0; i < kvp.Value.Count; i++)
{
var parameterPolicy = _policyFactory.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, _pool, pattern, policies);
}
}
}

View File

@ -19,7 +19,9 @@ namespace Microsoft.AspNetCore.Routing.Template
public class TemplateBinder
{
private readonly UrlEncoder _urlEncoder;
#pragma warning disable CS0618 // Type or member is obsolete
private readonly ObjectPool<UriBuildingContext> _pool;
#pragma warning restore CS0618 // Type or member is obsolete
private readonly (string parameterName, IRouteConstraint constraint)[] _constraints;
private readonly RouteValueDictionary _defaults;
@ -40,6 +42,9 @@ namespace Microsoft.AspNetCore.Routing.Template
/// <param name="pool">The <see cref="ObjectPool{T}"/>.</param>
/// <param name="template">The <see cref="RouteTemplate"/> to bind values to.</param>
/// <param name="defaults">The default values for <paramref name="template"/>.</param>
[Obsolete(
"This constructor is obsolete and will be marked internal in a furture release. Use the TemplateBinderFactory service " +
"to create TemplateBinder instances.")]
public TemplateBinder(
UrlEncoder urlEncoder,
ObjectPool<UriBuildingContext> pool,
@ -60,6 +65,9 @@ namespace Microsoft.AspNetCore.Routing.Template
/// <param name="parameterPolicies">
/// A list of (<see cref="string"/>, <see cref="IParameterPolicy"/>) pairs to evalute when producing a URI.
/// </param>
[Obsolete(
"This constructor is obsolete and will be marked internal in a future release. Use the TemplateBinderFactory service " +
"to create TemplateBinder instances.")]
public TemplateBinder(
UrlEncoder urlEncoder,
ObjectPool<UriBuildingContext> pool,
@ -110,6 +118,58 @@ namespace Microsoft.AspNetCore.Routing.Template
_slots = AssignSlots(_pattern, _filters);
}
internal TemplateBinder(
UrlEncoder urlEncoder,
#pragma warning disable CS0618 // Type or member is obsolete
ObjectPool<UriBuildingContext> pool,
#pragma warning restore CS0618 // Type or member is obsolete
RoutePattern pattern,
IEnumerable<(string parameterName, IParameterPolicy policy)> parameterPolicies)
{
if (urlEncoder == null)
{
throw new ArgumentNullException(nameof(urlEncoder));
}
if (pool == null)
{
throw new ArgumentNullException(nameof(pool));
}
if (pattern == null)
{
throw new ArgumentNullException(nameof(pattern));
}
// Parameter policies can be null.
_urlEncoder = urlEncoder;
_pool = pool;
_pattern = pattern;
_defaults = new RouteValueDictionary(pattern.Defaults);
_requiredKeys = pattern.RequiredValues.Keys.ToArray();
// Any default that doesn't have a corresponding parameter is a 'filter' and if a value
// is provided for that 'filter' it must match the value in defaults.
var filters = new RouteValueDictionary(_defaults);
for (var i = 0; i < pattern.Parameters.Count; i++)
{
filters.Remove(pattern.Parameters[i].Name);
}
_filters = filters.ToArray();
_constraints = parameterPolicies
?.Where(p => p.policy is IRouteConstraint)
.Select(p => (p.parameterName, (IRouteConstraint)p.policy))
.ToArray() ?? Array.Empty<(string, IRouteConstraint)>();
_parameterTransformers = parameterPolicies
?.Where(p => p.policy is IOutboundParameterTransformer)
.Select(p => (p.parameterName, (IOutboundParameterTransformer)p.policy))
.ToArray() ?? Array.Empty<(string, IOutboundParameterTransformer)>();
_slots = AssignSlots(_pattern, _filters);
}
// Step 1: Get the list of values we're going to try to use to match and generate this URI
public TemplateValuesResult GetValues(RouteValueDictionary ambientValues, RouteValueDictionary values)
{
@ -442,6 +502,7 @@ namespace Microsoft.AspNetCore.Routing.Template
}
}
#pragma warning disable CS0618 // Type or member is obsolete
private bool TryBindValuesCore(UriBuildingContext context, RouteValueDictionary acceptedValues)
{
// If we have any output parameter transformers, allow them a chance to influence the parameter values
@ -578,6 +639,7 @@ namespace Microsoft.AspNetCore.Routing.Template
}
return false;
}
#pragma warning restore CS0618 // Type or member is obsolete
/// <summary>
/// Compares two objects for equality as parts of a case-insensitive path.

View File

@ -0,0 +1,29 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Routing.Patterns;
namespace Microsoft.AspNetCore.Routing.Template
{
/// <summary>
/// A factory used to create <see cref="TemplateBinder"/> instances.
/// </summary>
public abstract class TemplateBinderFactory
{
/// <summary>
/// Creates a new <see cref="TemplateBinder"/> from the provided <paramref name="template"/> and
/// <paramref name="defaults"/>.
/// </summary>
/// <param name="template">The route template.</param>
/// <param name="defaults">A collection of extra default values that do not appear in the route template.</param>
/// <returns>A <see cref="TemplateBinder"/>.</returns>
public abstract TemplateBinder Create(RouteTemplate template, RouteValueDictionary defaults);
/// <summary>
/// Creates a new <see cref="TemplateBinder"/> from the provided <paramref name="pattern"/>.
/// </summary>
/// <param name="pattern">The <see cref="RoutePattern"/>.</param>
/// <returns>A <see cref="TemplateBinder"/>.</returns>
public abstract TemplateBinder Create(RoutePattern pattern);
}
}

View File

@ -8,13 +8,12 @@ using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Routing.DecisionTree;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.AspNetCore.Routing.Tree;
namespace Microsoft.AspNetCore.Routing.Internal
namespace Microsoft.AspNetCore.Routing.Tree
{
// A decision tree that matches link generation entries based on route data.
[DebuggerDisplay("{DebuggerDisplayString,nq}")]
public class LinkGenerationDecisionTree
internal class LinkGenerationDecisionTree
{
// Fallback value for cases where the ambient values weren't provided.
//

View File

@ -1,11 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Routing.Tree;
namespace Microsoft.AspNetCore.Routing.Internal
namespace Microsoft.AspNetCore.Routing.Tree
{
public readonly struct OutboundMatchResult
internal readonly struct OutboundMatchResult
{
public OutboundMatchResult(OutboundMatch match, bool isFallbackMatch)
{

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Routing.Internal;
@ -21,7 +20,9 @@ namespace Microsoft.AspNetCore.Routing.Tree
private readonly ILogger _logger;
private readonly ILogger _constraintLogger;
private readonly UrlEncoder _urlEncoder;
#pragma warning disable CS0618 // Type or member is obsolete
private readonly ObjectPool<UriBuildingContext> _objectPool;
#pragma warning restore CS0618 // Type or member is obsolete
private readonly IInlineConstraintResolver _constraintResolver;
/// <summary>
@ -30,9 +31,12 @@ namespace Microsoft.AspNetCore.Routing.Tree
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
/// <param name="objectPool">The <see cref="ObjectPool{UrlBuildingContext}"/>.</param>
/// <param name="constraintResolver">The <see cref="IInlineConstraintResolver"/>.</param>
[Obsolete("This constructor will be marked internal in a future release. Use the service provider to create instances of TreeRouteBuilder.")]
public TreeRouteBuilder(
ILoggerFactory loggerFactory,
#pragma warning disable CS0618 // Type or member is obsolete
ObjectPool<UriBuildingContext> objectPool,
#pragma warning restore CS0618 // Type or member is obsolete
IInlineConstraintResolver constraintResolver)
{
if (loggerFactory == null)
@ -240,6 +244,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
tree.AddEntry(entry);
}
#pragma warning disable CS0618 // Type or member is obsolete
return new TreeRouter(
trees.Values.OrderBy(tree => tree.Order).ToArray(),
OutboundEntries,
@ -248,6 +253,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
_logger,
_constraintLogger,
version);
#pragma warning restore CS0618 // Type or member is obsolete
}
/// <summary>

View File

@ -40,11 +40,14 @@ namespace Microsoft.AspNetCore.Routing.Tree
/// <param name="constraintLogger">The <see cref="ILogger"/> instance used
/// in <see cref="RouteConstraintMatcher"/>.</param>
/// <param name="version">The version of this route.</param>
[Obsolete("This constructor will be marked obsolete in a future release. Use the TreeRouterBuilder to create instances of TreeRouter.")]
public TreeRouter(
UrlMatchingTree[] trees,
IEnumerable<OutboundRouteEntry> linkGenerationEntries,
UrlEncoder urlEncoder,
#pragma warning disable CS0618 // Type or member is obsolete
ObjectPool<UriBuildingContext> objectPool,
#pragma warning restore CS0618 // Type or member is obsolete
ILogger routeLogger,
ILogger constraintLogger,
int version)

View File

@ -2,11 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Routing.Internal
namespace Microsoft.AspNetCore.Routing
{
public class UriBuilderContextPooledObjectPolicy : IPooledObjectPolicy<UriBuildingContext>
#pragma warning disable CS0618 // Type or member is obsolete
internal class UriBuilderContextPooledObjectPolicy : IPooledObjectPolicy<UriBuildingContext>
{
public UriBuildingContext Create()
{
@ -19,4 +21,5 @@ namespace Microsoft.AspNetCore.Routing.Internal
return true;
}
}
#pragma warning restore CS0618 // Type or member is obsolete
}

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.WebEncoders.Testing;
@ -6,6 +6,7 @@ using Xunit;
namespace Microsoft.AspNetCore.Routing.Internal
{
#pragma warning disable CS0618 // Type or member is obsolete
public class UriBuildingContextTest
{
[Fact]
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Routing.Internal
var value = "a/b b1/c";
var expected = "/UrlEncode[[a/b b1/c]]";
var uriBuilldingContext = new UriBuildingContext(urlTestEncoder);
// Act
uriBuilldingContext.EncodeValue(value, 0, value.Length, encodeSlashes: true);
@ -97,4 +98,5 @@ namespace Microsoft.AspNetCore.Routing.Internal
Assert.Equal(expected, uriBuilldingContext.ToPathString().Value);
}
}
#pragma warning restore CS0618 // Type or member is obsolete
}

View File

@ -5,6 +5,7 @@ using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Template;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.ObjectPool;
@ -82,8 +83,8 @@ namespace Microsoft.AspNetCore.Routing
return new DefaultLinkGenerator(
new DefaultParameterPolicyFactory(routeOptions, serviceProvider),
serviceProvider.GetRequiredService<TemplateBinderFactory>(),
new CompositeEndpointDataSource(routeOptions.Value.EndpointDataSources),
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
routeOptions,
NullLogger<DefaultLinkGenerator>.Instance,
serviceProvider);

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@ -32,10 +32,12 @@ namespace Microsoft.AspNetCore.Routing.Matching
public override Matcher Build()
{
#pragma warning disable CS0618 // Type or member is obsolete
var builder = new TreeRouteBuilder(
NullLoggerFactory.Instance,
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
new DefaultInlineConstraintResolver(Options.Create(new RouteOptions()), new TestServiceProvider()));
#pragma warning restore CS0618 // Type or member is obsolete
var selector = new DefaultEndpointSelector();

View File

@ -658,6 +658,7 @@ namespace Microsoft.AspNetCore.Routing
var expected = "/Home/Index?name=" + UrlEncoder.Default.Encode(nameRouteValue);
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
services.AddOptions();
services.AddRouting();
// This test encoder should not be used by Routing and should always use the default one.
services.AddSingleton<UrlEncoder>(new UrlTestEncoder());
@ -1520,6 +1521,7 @@ namespace Microsoft.AspNetCore.Routing
{
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
services.AddOptions();
services.AddRouting();
var context = new DefaultHttpContext

View File

@ -16,6 +16,7 @@ using Xunit;
namespace Microsoft.AspNetCore.Routing.Template.Tests
{
#pragma warning disable CS0618 // Type or member is obsolete
public class TemplateBinderTests
{
private readonly IInlineConstraintResolver _inlineConstraintResolver = GetInlineConstraintResolver();
@ -1480,4 +1481,5 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests
public Dictionary<string, string> Parameters { get; private set; }
}
}
#pragma warning restore CS0618 // Type or member is obsolete
}

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text.Encodings.Web;
@ -248,10 +248,12 @@ namespace Microsoft.AspNetCore.Routing.Tree
var objectPool = objectPoolProvider.Create(objectPolicy);
var constraintResolver = GetInlineConstraintResolver();
#pragma warning disable CS0618 // Type or member is obsolete
var builder = new TreeRouteBuilder(
NullLoggerFactory.Instance,
objectPool,
constraintResolver);
#pragma warning restore CS0618 // Type or member is obsolete
return builder;
}

View File

@ -23,8 +23,10 @@ namespace Microsoft.AspNetCore.Routing.Tree
{
private static readonly RequestDelegate NullHandler = (c) => Task.CompletedTask;
#pragma warning disable CS0618 // Type or member is obsolete
private static ObjectPool<UriBuildingContext> Pool = new DefaultObjectPoolProvider().Create(
new UriBuilderContextPooledObjectPolicy());
#pragma warning restore CS0618 // Type or member is obsolete
[Theory]
[InlineData("template/5", "template/{parameter:int}")]
@ -2073,6 +2075,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
return new DefaultInlineConstraintResolver(optionsMock.Object, new TestServiceProvider());
}
#pragma warning disable CS0618 // Type or member is obsolete
private static TreeRouteBuilder CreateBuilder()
{
var objectPoolProvider = new DefaultObjectPoolProvider();
@ -2086,6 +2089,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
constraintResolver);
return builder;
}
#pragma warning restore CS0618 // Type or member is obsolete
private static TreeRouter CreateTreeRouter(
string firstTemplate,