-
Notifications
You must be signed in to change notification settings - Fork 699
/
ActionDescriptorExtensions.cs
152 lines (127 loc) · 6.27 KB
/
ActionDescriptorExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
namespace Microsoft.AspNetCore.Mvc.Abstractions
{
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Versioning;
using System;
using System.Linq;
using System.Text;
using static Microsoft.AspNetCore.Mvc.Versioning.ApiVersionMapping;
using static System.Linq.Enumerable;
/// <summary>
/// Provides extension methods for the <see cref="ActionDescriptor"/> class.
/// </summary>
[CLSCompliant( false )]
public static class ActionDescriptorExtensions
{
/// <summary>
/// Gets the API version information associated with an action.
/// </summary>
/// <param name="action">The <see cref="ActionDescriptor">action</see> to evaluate.</param>
/// <returns>The <see cref="ApiVersionModel">API version information</see> for the action.</returns>
public static ApiVersionModel GetApiVersionModel( this ActionDescriptor action ) => action.GetApiVersionModel( Explicit );
/// <summary>
/// Gets the API version information associated with an action.
/// </summary>
/// <param name="action">The <see cref="ActionDescriptor">action</see> to evaluate.</param>
/// <param name="mapping">One or more of the <see cref="ApiVersionMapping"/> values.</param>
/// <returns>The <see cref="ApiVersionModel">API version information</see> for the action.</returns>
public static ApiVersionModel GetApiVersionModel( this ActionDescriptor action, ApiVersionMapping mapping )
{
switch ( mapping )
{
case Explicit:
return action.GetProperty<ApiVersionModel>() ?? ApiVersionModel.Empty;
case Implicit:
return action.GetProperty<ControllerModel>()?.GetProperty<ApiVersionModel>() ?? ApiVersionModel.Empty;
case Explicit | Implicit:
var model = action.GetProperty<ApiVersionModel>() ?? ApiVersionModel.Empty;
if ( model.IsApiVersionNeutral || model.DeclaredApiVersions.Count > 0 )
{
return model;
}
var implicitModel = action.GetProperty<ControllerModel>()?.GetProperty<ApiVersionModel>() ?? ApiVersionModel.Empty;
return new ApiVersionModel(
implicitModel.DeclaredApiVersions,
model.SupportedApiVersions,
model.DeprecatedApiVersions,
Empty<ApiVersion>(),
Empty<ApiVersion>() );
}
return ApiVersionModel.Empty;
}
/// <summary>
/// Returns a value indicating whether the provided action maps to the specified API version.
/// </summary>
/// <param name="action">The <see cref="ActionDescriptor">action</see> to evaluate.</param>
/// <param name="apiVersion">The <see cref="ApiVersion">API version</see> to test the mapping for.</param>
/// <returns>One of the <see cref="ApiVersionMapping"/> values.</returns>
public static ApiVersionMapping MappingTo( this ActionDescriptor action, ApiVersion? apiVersion )
{
var model = action.GetApiVersionModel();
if ( model.IsApiVersionNeutral )
{
return Explicit;
}
if ( apiVersion is null )
{
return None;
}
var mappedWithImplementation = model.DeclaredApiVersions.Contains( apiVersion ) &&
model.ImplementedApiVersions.Contains( apiVersion );
if ( mappedWithImplementation )
{
return Explicit;
}
var deriveFromParent = model.DeclaredApiVersions.Count == 0;
if ( deriveFromParent )
{
model = action.GetProperty<ControllerModel>()?.GetProperty<ApiVersionModel>();
if ( model is not null && model.DeclaredApiVersions.Contains( apiVersion ) )
{
return Implicit;
}
}
return None;
}
/// <summary>
/// Returns a value indicating whether the provided action maps to the specified API version.
/// </summary>
/// <param name="action">The <see cref="ActionDescriptor">action</see> to evaluate.</param>
/// <param name="apiVersion">The <see cref="ApiVersion">API version</see> to test the mapping for.</param>
/// <returns>True if the <paramref name="action"/> explicitly or implicitly maps to the specified
/// <paramref name="apiVersion">API version</paramref>; otherwise, false.</returns>
public static bool IsMappedTo( this ActionDescriptor action, ApiVersion? apiVersion ) => action.MappingTo( apiVersion ) > None;
internal static string ExpandSignature( this ActionDescriptor action )
{
if ( action is not ControllerActionDescriptor controllerAction )
{
return action.DisplayName ?? string.Empty;
}
var signature = new StringBuilder();
var controllerType = controllerAction.ControllerTypeInfo;
signature.Append( controllerType.GetTypeDisplayName() );
signature.Append( '.' );
signature.Append( controllerAction.MethodInfo.Name );
signature.Append( '(' );
using ( var parameter = action.Parameters.GetEnumerator() )
{
if ( parameter.MoveNext() )
{
var parameterType = parameter.Current.ParameterType;
signature.Append( parameterType.GetTypeDisplayName( false ) );
while ( parameter.MoveNext() )
{
parameterType = parameter.Current.ParameterType;
signature.Append( ", " );
signature.Append( parameterType.GetTypeDisplayName( false ) );
}
}
}
signature.Append( ") (" );
signature.Append( controllerType.Assembly.GetName().Name );
signature.Append( ')' );
return signature.ToString();
}
}
}