| File: Template\TemplatePart.cs | Web Access |
| Project: src\aspnetcore\src\Http\Routing\src\Microsoft.AspNetCore.Routing.csproj (Microsoft.AspNetCore.Routing) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.AspNetCore.Routing.Patterns; namespace Microsoft.AspNetCore.Routing.Template; /// <summary> /// Represents a part of a route template segment. /// </summary> [DebuggerDisplay("{DebuggerToString()}")] public class TemplatePart { /// <summary> /// Constructs a new <see cref="TemplatePart"/> instance. /// </summary> public TemplatePart() { } /// <summary> /// Constructs a new <see cref="TemplatePart"/> instance given a <paramref name="other"/>. /// </summary> /// <param name="other">A <see cref="RoutePatternPart"/> instance representing the route part.</param> public TemplatePart(RoutePatternPart other) { IsLiteral = other.IsLiteral || other.IsSeparator; IsParameter = other.IsParameter; if (other.IsLiteral && other is RoutePatternLiteralPart literal) { Text = literal.Content; } else if (other.IsParameter && other is RoutePatternParameterPart parameter) { // Text is unused by TemplatePart and assumed to be null when the part is a parameter. Name = parameter.Name; IsCatchAll = parameter.IsCatchAll; IsOptional = parameter.IsOptional; DefaultValue = parameter.Default; InlineConstraints = parameter.ParameterPolicies?.Select(p => new InlineConstraint(p)) ?? Enumerable.Empty<InlineConstraint>(); } else if (other.IsSeparator && other is RoutePatternSeparatorPart separator) { Text = separator.Content; IsOptionalSeperator = true; } else { // Unreachable throw new NotSupportedException(); } } /// <summary> /// Create a <see cref="TemplatePart"/> representing a literal route part. /// </summary> /// <param name="text">The text of the literate route part.</param> /// <returns>A <see cref="TemplatePart"/> instance.</returns> public static TemplatePart CreateLiteral(string text) { return new TemplatePart() { IsLiteral = true, Text = text, }; } /// <summary> /// Creates a <see cref="TemplatePart"/> representing a parameter part. /// </summary> /// <param name="name">The name of the parameter.</param> /// <param name="isCatchAll"><see langword="true"/> if the parameter is a catch-all parameter.</param> /// <param name="isOptional"><see langword="true"/> if the parameter is an optional parameter.</param> /// <param name="defaultValue">The default value of the parameter.</param> /// <param name="inlineConstraints">A collection of constraints associated with the parameter.</param> /// <returns>A <see cref="TemplatePart"/> instance.</returns> public static TemplatePart CreateParameter( string name, bool isCatchAll, bool isOptional, object? defaultValue, IEnumerable<InlineConstraint>? inlineConstraints) { ArgumentNullException.ThrowIfNull(name); return new TemplatePart() { IsParameter = true, Name = name, IsCatchAll = isCatchAll, IsOptional = isOptional, DefaultValue = defaultValue, InlineConstraints = inlineConstraints ?? Enumerable.Empty<InlineConstraint>(), }; } /// <summary> /// <see langword="true"/> if the route part is is a catch-all part (e.g. /*). /// </summary> public bool IsCatchAll { get; private set; } /// <summary> /// <see langword="true"/> if the route part is represents a literal value. /// </summary> [MemberNotNullWhen(true, nameof(Text))] public bool IsLiteral { get; private set; } /// <summary> /// <see langword="true"/> if the route part represents a parameterized value. /// </summary> public bool IsParameter { get; private set; } /// <summary> /// <see langword="true"/> if the route part represents an optional part. /// </summary> public bool IsOptional { get; private set; } /// <summary> /// <see langword="true"/> if the route part represents an optional separator. /// </summary> public bool IsOptionalSeperator { get; set; } /// <summary> /// The name of the route parameter. Can be null. /// </summary> public string? Name { get; private set; } /// <summary> /// The textual representation of the route parameter. Can be null. Used to represent route separators and literal parts. /// </summary> public string? Text { get; private set; } /// <summary> /// The default value for route parameters. Can be null. /// </summary> public object? DefaultValue { get; private set; } /// <summary> /// The constraints associates with a route parameter. /// </summary> public IEnumerable<InlineConstraint> InlineConstraints { get; private set; } = Enumerable.Empty<InlineConstraint>(); internal string? DebuggerToString() { if (IsParameter) { return "{" + (IsCatchAll ? "*" : string.Empty) + Name + (IsOptional ? "?" : string.Empty) + "}"; } else { return Text; } } /// <summary> /// Creates a <see cref="RoutePatternPart"/> for the route part designated by the <see cref="TemplatePart"/>. /// </summary> /// <returns>A <see cref="RoutePatternPart"/> instance.</returns> public RoutePatternPart ToRoutePatternPart() { if (IsLiteral && IsOptionalSeperator) { return RoutePatternFactory.SeparatorPart(Text!); } else if (IsLiteral) { return RoutePatternFactory.LiteralPart(Text!); } else { var kind = IsCatchAll ? RoutePatternParameterKind.CatchAll : IsOptional ? RoutePatternParameterKind.Optional : RoutePatternParameterKind.Standard; var constraints = InlineConstraints.Select(c => new RoutePatternParameterPolicyReference(c.Constraint)); return RoutePatternFactory.ParameterPart(Name!, DefaultValue, kind, constraints); } } }