Move UrlMatchingTree to shared source (#492)

Addresses #489
This commit is contained in:
Jass Bagga 2017-11-13 11:40:26 -08:00 committed by GitHub
parent 6c8af17e3a
commit 7f8ba171f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 169 additions and 238 deletions

View File

@ -2,7 +2,8 @@
"adx-nonshipping": {
"rules": [],
"packages": {
"Microsoft.AspNetCore.Routing.DecisionTree.Sources": {}
"Microsoft.AspNetCore.Routing.DecisionTree.Sources": {},
"Microsoft.AspNetCore.Routing.UrlMatchingTree.Sources": {}
}
},
"Default": {

View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26927.0
VisualStudioVersion = 15.0.27106.3000
MinimumVisualStudioVersion = 15.0.26730.03
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0E966C37-7334-4D96-AAF6-9F49FBD166E3}"
ProjectSection(SolutionItems) = preProject
@ -57,7 +57,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DispatcherSample", "samples
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Dispatcher.Performance", "benchmarks\Microsoft.AspNetCore.Dispatcher.Performance\Microsoft.AspNetCore.Dispatcher.Performance.csproj", "{30AF355D-E3AB-4FF5-8A59-A253AFEBA26A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Dispatcher.FunctionalTest", "test\Microsoft.AspNetCore.Dispatcher.FunctionalTest\Microsoft.AspNetCore.Dispatcher.FunctionalTest.csproj", "{32107601-C9BE-467B-894C-C9F2E35F03E4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Dispatcher.FunctionalTest", "test\Microsoft.AspNetCore.Dispatcher.FunctionalTest\Microsoft.AspNetCore.Dispatcher.FunctionalTest.csproj", "{32107601-C9BE-467B-894C-C9F2E35F03E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -2,21 +2,42 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
#if ROUTING
using Microsoft.AspNetCore.Routing.Template;
#elif DISPATCHER
using Microsoft.AspNetCore.Dispatcher;
#else
#error
#endif
#if ROUTING
namespace Microsoft.AspNetCore.Routing.Tree
#elif DISPATCHER
namespace Microsoft.AspNetCore.Dispatcher
#else
#error
#endif
{
#if ROUTING
/// <summary>
/// A candidate route to match incoming URLs in a <see cref="TreeRouter"/>.
/// </summary>
[DebuggerDisplay("{DebuggerToString(),nq}")]
public class InboundMatch
public
#elif DISPATCHER
[DebuggerDisplay("{DebuggerToString(),nq}")]
internal
#else
#error
#endif
class InboundMatch
{
/// <summary>
/// Gets or sets the <see cref="InboundRouteEntry"/>.
/// </summary>
public InboundRouteEntry Entry { get; set; }
#if ROUTING
/// <summary>
/// Gets or sets the <see cref="TemplateMatcher"/>.
/// </summary>
@ -26,5 +47,19 @@ namespace Microsoft.AspNetCore.Routing.Tree
{
return TemplateMatcher?.Template?.TemplateText;
}
}
#elif DISPATCHER
/// <summary>
/// Gets or sets the <see cref="RoutePatternMatcher"/>.
/// </summary>
public RoutePatternMatcher RoutePatternMatcher { get; set; }
private string DebuggerToString()
{
return RoutePatternMatcher?.RoutePattern?.RawText;
}
#else
#error
#endif
}
}

View File

@ -2,31 +2,40 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNetCore.Dispatcher.Patterns;
#if ROUTING
using Microsoft.AspNetCore.Routing.Template;
#elif DISPATCHER
using Microsoft.AspNetCore.Dispatcher;
#else
#error
#endif
#if ROUTING
namespace Microsoft.AspNetCore.Routing.Tree
#elif DISPATCHER
namespace Microsoft.AspNetCore.Dispatcher
#else
#error
#endif
{
#if ROUTING
/// <summary>
/// Used to build an <see cref="TreeRouter"/>. Represents a URL template tha will be used to match incoming
/// Used to build a <see cref="TreeRouter"/>. Represents a route template that will be used to match incoming
/// request URLs.
/// </summary>
public class InboundRouteEntry
public
#elif DISPATCHER
/// <summary>
/// Used to build a <see cref="TreeMatcher"/>. Represents a route pattern that will be used to match incoming
/// request URLs.
/// </summary>
internal
#else
#error
#endif
class InboundRouteEntry
{
/// <summary>
/// Gets or sets the route constraints.
/// </summary>
public IDictionary<string, IRouteConstraint> Constraints { get; set; }
/// <summary>
/// Gets or sets the route defaults.
/// </summary>
public RouteValueDictionary Defaults { get; set; }
/// <summary>
/// Gets or sets the <see cref="IRouter"/> to invoke when this entry matches.
/// </summary>
public IRouter Handler { get; set; }
/// <summary>
/// Gets or sets the order of the entry.
/// </summary>
@ -43,19 +52,54 @@ namespace Microsoft.AspNetCore.Routing.Tree
/// </remarks>
public decimal Precedence { get; set; }
#if ROUTING
/// <summary>
/// Gets or sets the name of the route.
/// </summary>
public string RouteName { get; set; }
/// <summary>
/// Gets or sets the route constraints.
/// </summary>
public IDictionary<string, IRouteConstraint> Constraints { get; set; }
/// <summary>
/// Gets or sets the <see cref="RouteTemplate"/>.
/// </summary>
public RouteTemplate RouteTemplate { get; set; }
/// <summary>
/// Gets or sets an arbitrary value associated with the entry.
/// Gets or sets the route defaults.
/// </summary>
public object Tag { get; set; }
public RouteValueDictionary Defaults { get; set; }
/// <summary>
/// Gets or sets the <see cref="IRouter"/> to invoke when this entry matches.
/// </summary>
public IRouter Handler { get; set; }
#elif DISPATCHER
/// <summary>
/// Gets or sets the array of endpoints associated with the entry.
/// </summary>
public Endpoint[] Endpoints { get; set; }
/// <summary>
/// Gets or sets the dispatcher value constraints.
/// </summary>
public IDictionary<string, IDispatcherValueConstraint> Constraints { get; set; }
/// <summary>
/// Gets or sets the dispatcher value defaults.
/// </summary>
public DispatcherValueCollection Defaults { get; set; }
/// <summary>
/// Gets or sets the <see cref="RoutePattern"/>.
/// </summary>
public RoutePattern RoutePattern { get; set; }
#else
#error
#endif
}
}

View File

@ -6,12 +6,16 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
#if ROUTING
namespace Microsoft.AspNetCore.Routing.Tree
#elif DISPATCHER
namespace Microsoft.AspNetCore.Dispatcher
#else
#error
#endif
{
/// <summary>
/// A node in a <see cref="UrlMatchingTree"/>.
/// </summary>
[DebuggerDisplay("{DebuggerToString(),nq}")]
#if ROUTING
public class UrlMatchingNode
{
/// <summary>
@ -25,11 +29,37 @@ namespace Microsoft.AspNetCore.Routing.Tree
Matches = new List<InboundMatch>();
Literals = new Dictionary<string, UrlMatchingNode>(StringComparer.OrdinalIgnoreCase);
}
private string DebuggerToString()
{
return $"Length: {Depth}, Matches: {string.Join(" | ", Matches?.Select(m => $"({m.TemplateMatcher.Template.TemplateText})"))}";
}
#elif DISPATCHER
internal class UrlMatchingNode
{
/// <summary>
/// Gets the length of the path to this node in the <see cref="UrlMatchingTree"/>.
/// Initializes a new instance of <see cref="UrlMatchingNode"/>.
/// </summary>
public int Depth { get; }
/// <param name="depth">The length of the path to this node in the <see cref="UrlMatchingTree"/>.</param>
public UrlMatchingNode(int depth)
{
Depth = depth;
Matches = new List<InboundMatch>();
Literals = new Dictionary<string, UrlMatchingNode>(StringComparer.OrdinalIgnoreCase);
}
private string DebuggerToString()
{
return $"Length: {Depth}, Matches: {string.Join(" | ", Matches?.Select(m => $"({m.RoutePatternMatcher.RoutePattern.RawText})"))}";
}
#else
#error
#endif
/// <summary>
/// Gets the length of the path to this node in the <see cref="UrlMatchingTree"/>.
/// </summary>
public int Depth { get; }
/// <summary>
/// Gets or sets a value indicating whether this node represents a catch all segment.
@ -51,31 +81,26 @@ namespace Microsoft.AspNetCore.Routing.Tree
/// <summary>
/// Gets or sets the <see cref="UrlMatchingNode"/> representing
/// parameter segments with constraints following this segment in the <see cref="TreeRouter"/>.
/// parameter segments with constraints following this segment.
/// </summary>
public UrlMatchingNode ConstrainedParameters { get; set; }
/// <summary>
/// Gets or sets the <see cref="UrlMatchingNode"/> representing
/// parameter segments following this segment in the <see cref="TreeRouter"/>.
/// parameter segments following this segment.
/// </summary>
public UrlMatchingNode Parameters { get; set; }
/// <summary>
/// Gets or sets the <see cref="UrlMatchingNode"/> representing
/// catch all parameter segments with constraints following this segment in the <see cref="TreeRouter"/>.
/// catch all parameter segments with constraints following this segment.
/// </summary>
public UrlMatchingNode ConstrainedCatchAlls { get; set; }
/// <summary>
/// Gets or sets the <see cref="UrlMatchingNode"/> representing
/// catch all parameter segments following this segment in the <see cref="TreeRouter"/>.
/// catch all parameter segments following this segment.
/// </summary>
public UrlMatchingNode CatchAlls { get; set; }
private string DebuggerToString()
{
return $"Length: {Depth}, Matches: {string.Join(" | ", Matches?.Select(m => $"({m.TemplateMatcher.Template.TemplateText})"))}";
}
}
}

View File

@ -1,12 +1,22 @@
// 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.
#if ROUTING
namespace Microsoft.AspNetCore.Routing.Tree
#elif DISPATCHER
namespace Microsoft.AspNetCore.Dispatcher
#else
#error
#endif
{
/// <summary>
/// A tree part of a <see cref="TreeRouter"/>.
/// </summary>
public class UrlMatchingTree
#if ROUTING
public
#elif DISPATCHER
internal
#else
#error
#endif
class UrlMatchingTree
{
/// <summary>
/// Initializes a new instance of <see cref="UrlMatchingTree"/>.
@ -25,6 +35,6 @@ namespace Microsoft.AspNetCore.Routing.Tree
/// <summary>
/// Gets the root of the <see cref="UrlMatchingTree"/>.
/// </summary>
public UrlMatchingNode Root { get; } = new UrlMatchingNode(length: 0);
public UrlMatchingNode Root { get; } = new UrlMatchingNode(0);
}
}

View File

@ -3,11 +3,16 @@
<PropertyGroup>
<Description>API for dispatching.</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<DefineConstants>$(DefineConstants);DISPATCHER</DefineConstants>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;routing</PackageTags>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\shared\Microsoft.AspNetCore.Routing.UrlMatchingTree.Sources\**\*.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.Dispatcher.Abstractions\Microsoft.AspNetCore.Dispatcher.Abstractions.csproj" />
</ItemGroup>

View File

@ -1,29 +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.
using System.Diagnostics;
namespace Microsoft.AspNetCore.Dispatcher
{
/// <summary>
/// A candidate endpoint to match incoming URLs in a <c>TreeMatcher</c>.
/// </summary>
[DebuggerDisplay("{DebuggerToString(),nq}")]
public class InboundMatch
{
/// <summary>
/// Gets or sets the <see cref="InboundRouteEntry"/>.
/// </summary>
public InboundRouteEntry Entry { get; set; }
/// <summary>
/// Gets or sets the <see cref="RoutePatternMatcher"/>.
/// </summary>
public RoutePatternMatcher RoutePatternMatcher { get; set; }
private string DebuggerToString()
{
return RoutePatternMatcher?.RoutePattern?.RawText;
}
}
}

View File

@ -1,51 +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.
using System.Collections.Generic;
using Microsoft.AspNetCore.Dispatcher.Patterns;
namespace Microsoft.AspNetCore.Dispatcher
{
/// <summary>
/// Used to build a <see cref="TreeMatcher"/>. Represents a route pattern that will be used to match incoming
/// request URLs.
/// </summary>
public class InboundRouteEntry
{
/// <summary>
/// Gets or sets the dispatcher value constraints.
/// </summary>
public IDictionary<string, IDispatcherValueConstraint> Constraints { get; set; }
/// <summary>
/// Gets or sets the dispatcher value defaults.
/// </summary>
public DispatcherValueCollection Defaults { get; set; }
/// <summary>
/// Gets or sets the order of the entry.
/// </summary>
/// <remarks>
/// Entries are ordered first by <see cref="Order"/> (ascending) then by <see cref="Precedence"/> (descending).
/// </remarks>
public int Order { get; set; }
/// <summary>
/// Gets or sets the precedence of the entry.
/// </summary>
/// <remarks>
/// Entries are ordered first by <see cref="Order"/> (ascending) then by <see cref="Precedence"/> (descending).
/// </remarks>
public decimal Precedence { get; set; }
/// <summary>
/// Gets or sets the <see cref="RoutePattern"/>.
/// </summary>
public RoutePattern RoutePattern { get; set; }
/// <summary>
/// Gets or sets an arbitrary value associated with the entry.
/// </summary>
public object Tag { get; set; }
}
}

View File

@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Dispatcher
continue;
}
await SelectEndpointAsync(context, (Endpoint[])entry.Tag);
await SelectEndpointAsync(context, (entry.Endpoints));
if (context.ShortCircuit != null)
{
Logger.RequestShortCircuited(context);
@ -184,7 +184,7 @@ namespace Microsoft.AspNetCore.Dispatcher
private InboundRouteEntry MapInbound(
RoutePattern routePattern,
object tag,
Endpoint[] endpoints,
int order)
{
if (routePattern == null)
@ -197,7 +197,7 @@ namespace Microsoft.AspNetCore.Dispatcher
Precedence = RoutePrecedence.ComputeInbound(routePattern),
RoutePattern = routePattern,
Order = order,
Tag = tag
Endpoints = endpoints,
};
var constraintBuilder = new DispatcherValueConstraintBuilder(_constraintFactory, routePattern.RawText);

View File

@ -1,81 +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.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Microsoft.AspNetCore.Dispatcher
{
/// <summary>
/// A node in a <see cref="UrlMatchingTree"/>.
/// </summary>
[DebuggerDisplay("{DebuggerToString(),nq}")]
public class UrlMatchingNode
{
/// <summary>
/// Initializes a new instance of <see cref="UrlMatchingNode"/>.
/// </summary>
/// <param name="depth">The length of the path to this node in the <see cref="UrlMatchingTree"/>.</param>
public UrlMatchingNode(int depth)
{
Depth = depth;
Matches = new List<InboundMatch>();
Literals = new Dictionary<string, UrlMatchingNode>(StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Gets the length of the path to this node in the <see cref="UrlMatchingTree"/>.
/// </summary>
public int Depth { get; }
/// <summary>
/// Gets or sets a value indicating whether this node represents a catch all segment.
/// </summary>
public bool IsCatchAll { get; set; }
/// <summary>
/// Gets the list of matching route entries associated with this node.
/// </summary>
/// <remarks>
/// These entries are sorted by precedence then template.
/// </remarks>
public List<InboundMatch> Matches { get; }
/// <summary>
/// Gets the literal segments following this segment.
/// </summary>
public Dictionary<string, UrlMatchingNode> Literals { get; }
/// <summary>
/// Gets or sets the <see cref="UrlMatchingNode"/> representing
/// parameter segments with constraints following this segment in the <see cref="TreeMatcher"/>.
/// </summary>
public UrlMatchingNode ConstrainedParameters { get; set; }
/// <summary>
/// Gets or sets the <see cref="UrlMatchingNode"/> representing
/// parameter segments following this segment in the <see cref="TreeMatcher"/>.
/// </summary>
public UrlMatchingNode Parameters { get; set; }
/// <summary>
/// Gets or sets the <see cref="UrlMatchingNode"/> representing
/// catch all parameter segments with constraints following this segment in the <see cref="TreeMatcher"/>.
/// </summary>
public UrlMatchingNode ConstrainedCatchAlls { get; set; }
/// <summary>
/// Gets or sets the <see cref="UrlMatchingNode"/> representing
/// catch all parameter segments following this segment in the <see cref="TreeMatcher"/>.
/// </summary>
public UrlMatchingNode CatchAlls { get; set; }
private string DebuggerToString()
{
return $"Length: {Depth}, Matches: {string.Join(" | ", Matches?.Select(m => $"({m.RoutePatternMatcher.RoutePattern.RawText})"))}";
}
}
}

View File

@ -1,30 +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.Dispatcher
{
/// <summary>
/// A tree part of a <see cref="TreeMatcher"/>.
/// </summary>
public class UrlMatchingTree
{
/// <summary>
/// Initializes a new instance of <see cref="UrlMatchingTree"/>.
/// </summary>
/// <param name="order">The order associated with endpoints in this <see cref="UrlMatchingTree"/>.</param>
public UrlMatchingTree(int order)
{
Order = order;
}
/// <summary>
/// Gets the order of the endpoints associated with this <see cref="UrlMatchingTree"/>.
/// </summary>
public int Order { get; }
/// <summary>
/// Gets the root of the <see cref="UrlMatchingTree"/>.
/// </summary>
public UrlMatchingNode Root { get; } = new UrlMatchingNode(depth: 0);
}
}

View File

@ -6,6 +6,7 @@ Commonly used types:
Microsoft.AspNetCore.Routing.Route
Microsoft.AspNetCore.Routing.RouteCollection</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<DefineConstants>$(DefineConstants);ROUTING</DefineConstants>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;routing</PackageTags>
@ -13,6 +14,7 @@ Microsoft.AspNetCore.Routing.RouteCollection</Description>
<ItemGroup>
<Compile Include="..\..\shared\Microsoft.AspNetCore.Routing.DecisionTree.Sources\**\*.cs" />
<Compile Include="..\..\shared\Microsoft.AspNetCore.Routing.UrlMatchingTree.Sources\**\*.cs" />
</ItemGroup>
<ItemGroup>