From e53a9f57dba3d53cddcc6393d08372316fac64a3 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Fri, 3 Aug 2018 13:48:55 -0700 Subject: [PATCH] adding more docs --- .../Matching/CandidateSet.cs | 36 ++++++++++++++-- .../Matching/CandidateState.cs | 30 ++++++++++++++ .../Matching/EndpointMetadataComparer.cs | 41 +++++++++++++++++++ .../Matching/EndpointSelector.cs | 17 ++++++++ .../Matching/HttpMethodMatcherPolicy.cs | 26 ++++++++++++ .../Matching/IEndpointComparerPolicy.cs | 22 ++++++++++ .../Matching/IEndpointSelectorPolicy.cs | 18 ++++++++ .../Matching/MatcherEndpoint.cs | 26 ++++++++++++ .../Matching/MatcherPolicy.cs | 18 ++++++++ 9 files changed, 230 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.Routing/Matching/CandidateSet.cs b/src/Microsoft.AspNetCore.Routing/Matching/CandidateSet.cs index dc51752923..be134bf6ce 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/CandidateSet.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/CandidateSet.cs @@ -6,6 +6,11 @@ using System.Runtime.CompilerServices; namespace Microsoft.AspNetCore.Routing.Matching { + /// + /// Represents a set of candidates that have been matched + /// by the routing system. Used by implementations of + /// and . + /// public sealed class CandidateSet { // We inline storage for 4 candidates here to avoid allocations in common @@ -18,8 +23,18 @@ namespace Microsoft.AspNetCore.Routing.Matching private CandidateState[] _additionalCandidates; - // Provided to make testing possible/easy for someone implementing - // an EndpointSelector. + /// + /// + /// Initializes a new instances of the candidate set structure with the provided list of endpoints + /// and associated scores. + /// + /// + /// The constructor is provided to enable unit tests of implementations of + /// and . + /// + /// + /// The list of endpoints, sorted in descending priority order. + /// The list of endpoint scores. . public CandidateSet(MatcherEndpoint[] endpoints, int[] scores) { Count = endpoints.Length; @@ -112,12 +127,25 @@ namespace Microsoft.AspNetCore.Routing.Matching } } + /// + /// Gets the count of candidates in the set. + /// public int Count { get; } - // Note that this is a ref-return because of both mutability and performance. - // We don't want to copy these fat structs if it can be avoided. + /// + /// Gets the associated with the candidate + /// at . + /// + /// The candidate index. + /// + /// A reference to the . The result is returned by reference + /// and intended to be mutated. + /// public ref CandidateState this[int index] { + // Note that this is a ref-return because of both mutability and performance. + // We don't want to copy these fat structs if it can be avoided. + // PERF: Force inlining [MethodImpl(MethodImplOptions.AggressiveInlining)] get diff --git a/src/Microsoft.AspNetCore.Routing/Matching/CandidateState.cs b/src/Microsoft.AspNetCore.Routing/Matching/CandidateState.cs index 4cb525bfac..cf27c04c78 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/CandidateState.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/CandidateState.cs @@ -3,6 +3,9 @@ namespace Microsoft.AspNetCore.Routing.Matching { + /// + /// The mutable state associated with a candidate in a . + /// public struct CandidateState { internal CandidateState(MatcherEndpoint endpoint, int score) @@ -14,12 +17,39 @@ namespace Microsoft.AspNetCore.Routing.Matching Values = null; } + /// + /// Gets the . + /// public MatcherEndpoint Endpoint { get; } + /// + /// Gets the score of the within the current + /// . + /// + /// + /// + /// Candidates within a set are ordered in priority order and then assigned a + /// sequential score value based on that ordering. Candiates with the same + /// score are considered to have equal priority. + /// + /// + /// The score values are used in the to determine + /// whether a set of matching candidates is an ambiguous match. + /// + /// public int Score { get; } + /// + /// Gets or sets a value which indicates where the is considered + /// a valid candiate for the current request. Set this value to false to exclude an + /// from consideration. + /// public bool IsValidCandidate { get; set; } + /// + /// Gets or sets the associated with the + /// and the current request. + /// public RouteValueDictionary Values { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/EndpointMetadataComparer.cs b/src/Microsoft.AspNetCore.Routing/Matching/EndpointMetadataComparer.cs index 6c617f5d03..b2a7b9ec00 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/EndpointMetadataComparer.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/EndpointMetadataComparer.cs @@ -6,10 +6,30 @@ using System.Collections.Generic; namespace Microsoft.AspNetCore.Routing.Matching { + /// + /// A base class for implementations that use + /// a specific type of metadata from for comparison. + /// Useful for implementing . + /// + /// + /// The type of metadata to compare. Typically this is a type of metadata related + /// to the application concern being handled. + /// public abstract class EndpointMetadataComparer : IComparer where TMetadata : class { public static readonly EndpointMetadataComparer Default = new DefaultComparer(); + /// + /// Compares two objects and returns a value indicating whether one is less than, equal to, + /// or greater than the other. + /// + /// The first object to compare. + /// The second object to compare. + /// + /// An implementation of this method must return a value less than zero if + /// x is less than y, zero if x is equal to y, or a value greater than zero if x is + /// greater than y. + /// public int Compare(Endpoint x, Endpoint y) { if (x == null) @@ -25,11 +45,32 @@ namespace Microsoft.AspNetCore.Routing.Matching return CompareMetadata(GetMetadata(x), GetMetadata(y)); } + /// + /// Gets the metadata of type from the provided endpoint. + /// + /// The . + /// The instance or null. protected virtual TMetadata GetMetadata(Endpoint endpoint) { return endpoint.Metadata.GetMetadata(); } + /// + /// Compares two instances. + /// + /// The first object to compare. + /// The second object to compare. + /// + /// An implementation of this method must return a value less than zero if + /// x is less than y, zero if x is equal to y, or a value greater than zero if x is + /// greater than y. + /// + /// + /// The base-class implementation of this method will compare metadata based on whether + /// or not they are null. The effect of this is that when endpoints are being + /// compared, the endpoint that defines an instance of + /// will be considered higher priority. + /// protected virtual int CompareMetadata(TMetadata x, TMetadata y) { // The default policy is that if x endpoint defines TMetadata, and diff --git a/src/Microsoft.AspNetCore.Routing/Matching/EndpointSelector.cs b/src/Microsoft.AspNetCore.Routing/Matching/EndpointSelector.cs index 0af172bdca..436c3df6f5 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/EndpointSelector.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/EndpointSelector.cs @@ -6,8 +6,25 @@ using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing.Matching { + /// + /// A service that is responsible for the final selection + /// decision. To use a custom register an implementation + /// of in the dependency injection container as a singleton. + /// public abstract class EndpointSelector { + /// + /// Asynchronously selects an from the . + /// + /// The associated with the current request. + /// The associated with the current request. + /// The . + /// A that completes asynchronously once endpoint selection is complete. + /// + /// An should assign the , + /// , and properties + /// once an endpoint is selected. + /// public abstract Task SelectAsync( HttpContext httpContext, IEndpointFeature feature, diff --git a/src/Microsoft.AspNetCore.Routing/Matching/HttpMethodMatcherPolicy.cs b/src/Microsoft.AspNetCore.Routing/Matching/HttpMethodMatcherPolicy.cs index 9968395b29..0be502b1a2 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/HttpMethodMatcherPolicy.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/HttpMethodMatcherPolicy.cs @@ -12,6 +12,10 @@ using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Routing.Matching { + /// + /// An that implements filtering and selection by + /// the HTTP method of a request. + /// public sealed class HttpMethodMatcherPolicy : MatcherPolicy, IEndpointComparerPolicy, INodeBuilderPolicy { // Used in tests @@ -25,12 +29,23 @@ namespace Microsoft.AspNetCore.Routing.Matching // Used in tests internal const string AnyMethod = "*"; + /// + /// For framework use only. + /// public IComparer Comparer => new HttpMethodMetadataEndpointComparer(); // The order value is chosen to be less than 0, so that it comes before naively // written policies. + /// + /// For framework use only. + /// public override int Order => -1000; + /// + /// For framework use only. + /// + /// + /// public bool AppliesToNode(IReadOnlyList endpoints) { if (endpoints == null) @@ -49,6 +64,11 @@ namespace Microsoft.AspNetCore.Routing.Matching return false; } + /// + /// For framework use only. + /// + /// + /// public IReadOnlyList GetEdges(IReadOnlyList endpoints) { // The algorithm here is designed to be preserve the order of the endpoints @@ -180,6 +200,12 @@ namespace Microsoft.AspNetCore.Routing.Matching } } + /// + /// For framework use only. + /// + /// + /// + /// public PolicyJumpTable BuildJumpTable(int exitDestination, IReadOnlyList edges) { var destinations = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/src/Microsoft.AspNetCore.Routing/Matching/IEndpointComparerPolicy.cs b/src/Microsoft.AspNetCore.Routing/Matching/IEndpointComparerPolicy.cs index 9c187a6fec..a1010c181c 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/IEndpointComparerPolicy.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/IEndpointComparerPolicy.cs @@ -5,8 +5,30 @@ using System.Collections.Generic; namespace Microsoft.AspNetCore.Routing.Matching { + /// + /// A interface that can be implemented to sort + /// endpoints. Implementations of must + /// inherit from and should be registered in + /// the dependency injection container as singleton services of type . + /// + /// + /// + /// Candidates in a are sorted based on their priority. Defining + /// a adds an additional criterion to the sorting + /// operation used to order candidates. + /// + /// + /// As an example, the implementation of implements + /// to ensure that endpoints matching specific HTTP + /// methods are sorted with a higher priority than endpoints without a specific HTTP method + /// requirement. + /// + /// public interface IEndpointComparerPolicy { + /// + /// Gets an that will be used to sort the endpoints. + /// IComparer Comparer { get; } } } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/IEndpointSelectorPolicy.cs b/src/Microsoft.AspNetCore.Routing/Matching/IEndpointSelectorPolicy.cs index 63fe7dd8fd..7dfd04b7bd 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/IEndpointSelectorPolicy.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/IEndpointSelectorPolicy.cs @@ -5,8 +5,26 @@ using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Routing.Matching { + /// + /// A interface that can implemented to filter endpoints + /// in a . Implementations of must + /// inherit from and should be registered in + /// the dependency injection container as singleton services of type . + /// public interface IEndpointSelectorPolicy { + /// + /// Applies the policy to the . + /// + /// + /// The associated with the current request. + /// + /// The . + /// + /// Implementations of should implement this method + /// and filter the set of candidates in the by setting + /// to false where desired. + /// void Apply(HttpContext httpContext, CandidateSet candidates); } } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpoint.cs b/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpoint.cs index 194fb0dc3d..ff5067cb81 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpoint.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/MatcherEndpoint.cs @@ -9,6 +9,9 @@ using Microsoft.AspNetCore.Routing.Patterns; namespace Microsoft.AspNetCore.Routing.Matching { + /// + /// Represents an that can be used in URL matching or URL generation. + /// public sealed class MatcherEndpoint : Endpoint { internal static readonly Func EmptyInvoker = (next) => @@ -16,6 +19,16 @@ namespace Microsoft.AspNetCore.Routing.Matching return (context) => Task.CompletedTask; }; + /// + /// Initializes a new instance of the class. + /// + /// The delegate to invoke to create a . + /// The to use in URL matching. + /// The order assigned to the endpoint. + /// + /// The or metadata associated with the endpoint. + /// + /// The informational display name of the endpoint. public MatcherEndpoint( Func invoker, RoutePattern routePattern, @@ -39,10 +52,23 @@ namespace Microsoft.AspNetCore.Routing.Matching Order = order; } + /// + /// Gets the invoker. The invoker is a delegate used to create a . + /// public Func Invoker { get; } + /// + /// Gets the order value of endpoint. + /// + /// + /// The order value provides absolute control over the priority + /// of an endpoint. Endpoints with a lower numeric value of order have higher priority. + /// public int Order { get; } + /// + /// Gets the associated with the endpoint. + /// public RoutePattern RoutePattern { get; } } } diff --git a/src/Microsoft.AspNetCore.Routing/Matching/MatcherPolicy.cs b/src/Microsoft.AspNetCore.Routing/Matching/MatcherPolicy.cs index 92d715c936..05a654efd9 100644 --- a/src/Microsoft.AspNetCore.Routing/Matching/MatcherPolicy.cs +++ b/src/Microsoft.AspNetCore.Routing/Matching/MatcherPolicy.cs @@ -1,10 +1,28 @@ // 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.Matching; + namespace Microsoft.AspNetCore.Routing { + /// + /// Defines a policy that applies behaviors to the URL matcher. Implementations + /// of and related interfaces must be registered + /// in the dependency injection container as singleton services of type + /// . + /// + /// + /// implementations can implement the following + /// interfaces , , + /// and . + /// public abstract class MatcherPolicy { + /// + /// Gets a value that determines the order the should + /// be applied. Policies are applied in ascending numeric value of the + /// property. + /// public abstract int Order { get; } } }