@@ -6,6 +6,7 @@ namespace Microsoft.Extensions.DependencyInjection;
6
6
using Asp . Versioning . ApiExplorer ;
7
7
using Asp . Versioning . Routing ;
8
8
using Microsoft . AspNetCore . Http ;
9
+ using Microsoft . AspNetCore . Http . Json ;
9
10
using Microsoft . AspNetCore . Routing ;
10
11
using Microsoft . Extensions . DependencyInjection . Extensions ;
11
12
using Microsoft . Extensions . Options ;
@@ -90,26 +91,7 @@ private static void AddApiVersioningServices( IServiceCollection services )
90
91
services . TryAddEnumerable ( Singleton < IApiVersionMetadataCollationProvider , EndpointApiVersionMetadataCollationProvider > ( ) ) ;
91
92
services . Replace ( WithLinkGeneratorDecorator ( services ) ) ;
92
93
TryAddProblemDetailsRfc7231Compliance ( services ) ;
93
- }
94
-
95
- // REF: https://github.com/dotnet/runtime/blob/master/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs#L125
96
- private static Type GetImplementationType ( this ServiceDescriptor descriptor )
97
- {
98
- if ( descriptor . ImplementationType != null )
99
- {
100
- return descriptor . ImplementationType ;
101
- }
102
- else if ( descriptor . ImplementationInstance != null )
103
- {
104
- return descriptor . ImplementationInstance . GetType ( ) ;
105
- }
106
- else if ( descriptor . ImplementationFactory != null )
107
- {
108
- var typeArguments = descriptor . ImplementationFactory . GetType ( ) . GenericTypeArguments ;
109
- return typeArguments [ 1 ] ;
110
- }
111
-
112
- throw new InvalidOperationException ( ) ;
94
+ TryAddErrorObjectJsonOptions ( services ) ;
113
95
}
114
96
115
97
private static ServiceDescriptor WithLinkGeneratorDecorator ( IServiceCollection services )
@@ -127,12 +109,31 @@ private static ServiceDescriptor WithLinkGeneratorDecorator( IServiceCollection
127
109
128
110
if ( factory == null )
129
111
{
130
- var decoratedType = descriptor . GetImplementationType ( ) ;
131
- var decoratorType = typeof ( ApiVersionLinkGenerator < > ) . MakeGenericType ( decoratedType ) ;
112
+ // REF: https://github.com/dotnet/aspnetcore/blob/main/src/Http/Routing/src/DependencyInjection/RoutingServiceCollectionExtensions.cs#L96
113
+ // REF: https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs#L292
114
+ var decoratedType = descriptor switch
115
+ {
116
+ { ImplementationType : var type } when type is not null => type ,
117
+ { ImplementationInstance : var instance } when instance is not null => instance . GetType ( ) ,
118
+ _ => throw new InvalidOperationException ( ) ,
119
+ } ;
132
120
133
121
services . Replace ( Describe ( decoratedType , decoratedType , lifetime ) ) ;
134
122
135
- return Describe ( typeof ( LinkGenerator ) , decoratorType , lifetime ) ;
123
+ LinkGenerator NewFactory ( IServiceProvider serviceProvider )
124
+ {
125
+ var instance = ( LinkGenerator ) serviceProvider . GetRequiredService ( decoratedType ! ) ;
126
+ var source = serviceProvider . GetRequiredService < IApiVersionParameterSource > ( ) ;
127
+
128
+ if ( source . VersionsByUrl ( ) )
129
+ {
130
+ instance = new ApiVersionLinkGenerator ( instance ) ;
131
+ }
132
+
133
+ return instance ;
134
+ }
135
+
136
+ return Describe ( typeof ( LinkGenerator ) , NewFactory , lifetime ) ;
136
137
}
137
138
else
138
139
{
@@ -177,4 +178,24 @@ static bool IsDefaultProblemDetailsWriter( ServiceDescriptor serviceDescriptor )
177
178
static Rfc7231ProblemDetailsWriter NewProblemDetailsWriter ( IServiceProvider serviceProvider , Type decoratedType ) =>
178
179
new ( ( IProblemDetailsWriter ) serviceProvider . GetRequiredService ( decoratedType ) ) ;
179
180
}
181
+
182
+ private static void TryAddErrorObjectJsonOptions ( IServiceCollection services )
183
+ {
184
+ var serviceType = typeof ( IProblemDetailsWriter ) ;
185
+ var implementationType = typeof ( ErrorObjectWriter ) ;
186
+
187
+ for ( var i = 0 ; i < services . Count ; i ++ )
188
+ {
189
+ var service = services [ i ] ;
190
+
191
+ // inheritance is intentionally not considered here because it will require a user-defined
192
+ // JsonSerlizerContext and IConfigureOptions<JsonOptions>
193
+ if ( service . ServiceType == serviceType &&
194
+ service . ImplementationType == implementationType )
195
+ {
196
+ services . TryAddEnumerable ( Singleton < IConfigureOptions < JsonOptions > , ErrorObjectJsonOptionsSetup > ( ) ) ;
197
+ return ;
198
+ }
199
+ }
200
+ }
180
201
}
0 commit comments