diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Asp.Versioning.OpenApi.csproj b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Asp.Versioning.OpenApi.csproj
index c4007148..01d47b6d 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Asp.Versioning.OpenApi.csproj
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Asp.Versioning.OpenApi.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Class.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Class.cs
index 4d4ec845..3ae15fda 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Class.cs
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Class.cs
@@ -10,7 +10,9 @@ namespace Asp.Versioning.OpenApi.Reflection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
using static System.Linq.Expressions.Expression;
+using static System.Runtime.CompilerServices.UnsafeAccessorKind;
// HACK: all of these types are internal in Microsoft.AspNetCore.OpenApi
// REF: https://github.com/dotnet/aspnetcore/tree/main/src/OpenApi/src
@@ -18,80 +20,62 @@ internal static class Class
{
public static class OpenApiDocumentService
{
- private static readonly Func factory = NewFactory();
-
- public static object New( IServiceProvider serviceProvider, string documentName ) => factory( serviceProvider, documentName );
-
- private static Func NewFactory()
+ public static object New( IServiceProvider serviceProvider, string documentName )
{
- var constructor = Type.OpenApiDocumentService.GetConstructors().Single();
- var serviceProvider = Parameter( typeof( IServiceProvider ), "serviceProvider" );
- var documentName = Parameter( typeof( string ), "documentName" );
- var getRequiredService = typeof( ServiceProviderServiceExtensions ).GetMethod(
- nameof( ServiceProviderServiceExtensions.GetRequiredService ),
- [typeof( IServiceProvider ), typeof( System.Type )] )!;
- var apiDescriptionGroupCollectionProvider = typeof( IApiDescriptionGroupCollectionProvider );
- var hostEnvironment = typeof( IHostEnvironment );
- var optionsMonitor = typeof( IOptionsMonitor );
- var server = typeof( IServer );
- var body = Expression.New(
- constructor,
+ var apiDescriptionGroupCollectionProvider = serviceProvider.GetRequiredService();
+ var hostEnvironment = serviceProvider.GetRequiredService();
+ var optionsMonitor = serviceProvider.GetRequiredService>();
+ var server = serviceProvider.GetRequiredService();
+
+ return OpenApiDocumentServiceCtor(
documentName,
- Convert( Call( getRequiredService, serviceProvider, Constant( apiDescriptionGroupCollectionProvider ) ), apiDescriptionGroupCollectionProvider ),
- Convert( Call( getRequiredService, serviceProvider, Constant( hostEnvironment ) ), hostEnvironment ),
- Convert( Call( getRequiredService, serviceProvider, Constant( optionsMonitor ) ), optionsMonitor ),
+ apiDescriptionGroupCollectionProvider,
+ hostEnvironment,
+ optionsMonitor,
serviceProvider,
- Convert( Call( getRequiredService, serviceProvider, Constant( server ) ), server ) );
- var lambda = Lambda>( body, serviceProvider, documentName );
-
- return lambda.Compile();
+ server );
}
+
+ [UnsafeAccessor( Constructor )]
+ [return: UnsafeAccessorType( Type.Name.OpenApiDocumentService )]
+ private static extern object OpenApiDocumentServiceCtor(
+ string documentName,
+ IApiDescriptionGroupCollectionProvider apiDescriptionGroupCollectionProvider,
+ IHostEnvironment hostEnvironment,
+ IOptionsMonitor optionsMonitor,
+ IServiceProvider serviceProvider,
+ IServer server );
}
public static class OpenApiSchemaService
{
- private static readonly Func factory = NewFactory();
-
- public static object New( IServiceProvider serviceProvider, string documentName ) => factory( serviceProvider, documentName );
-
- private static Func NewFactory()
+ public static object New( IServiceProvider serviceProvider, string documentName )
{
- var constructor = Type.OpenApiSchemaService.GetConstructors().Single();
- var serviceProvider = Parameter( typeof( IServiceProvider ), "serviceProvider" );
- var documentName = Parameter( typeof( string ), "documentName" );
- var getRequiredService = typeof( ServiceProviderServiceExtensions ).GetMethod(
- nameof( ServiceProviderServiceExtensions.GetRequiredService ),
- [typeof( IServiceProvider ), typeof( System.Type )] )!;
- var jsonOptions = typeof( IOptions );
- var optionsMonitor = typeof( IOptionsMonitor );
- var body = Expression.New(
- constructor,
- documentName,
- Convert( Call( getRequiredService, serviceProvider, Constant( jsonOptions ) ), jsonOptions ),
- Convert( Call( getRequiredService, serviceProvider, Constant( optionsMonitor ) ), optionsMonitor ) );
- var lambda = Lambda>( body, serviceProvider, documentName );
+ var jsonOptions = serviceProvider.GetRequiredService>();
+ var optionsMonitor = serviceProvider.GetRequiredService>();
- return lambda.Compile();
+ return OpenApiSchemaServiceCtor( documentName, jsonOptions, optionsMonitor );
}
+
+ [UnsafeAccessor( Constructor )]
+ [return: UnsafeAccessorType( Type.Name.OpenApiSchemaService )]
+ private static extern object OpenApiSchemaServiceCtor(
+ string documentName,
+ IOptions jsonOptions,
+ IOptionsMonitor optionsMonitor );
}
public static class OpenApiDocumentProvider
{
- private static readonly Func factory = NewFactory();
-
- public static object New( IServiceProvider serviceProvider ) => factory( serviceProvider );
+ public static object New( IServiceProvider serviceProvider ) => OpenApiDocumentProviderCtor( serviceProvider );
- private static Func NewFactory()
- {
- var constructor = Type.OpenApiDocumentProvider.GetConstructors().Single();
- var serviceProvider = Parameter( typeof( IServiceProvider ), "serviceProvider" );
- var body = Expression.New( constructor, serviceProvider );
- var lambda = Lambda>( body, serviceProvider );
-
- return lambda.Compile();
- }
+ [UnsafeAccessor( Constructor )]
+ [return: UnsafeAccessorType( Type.Name.OpenApiDocumentProvider )]
+ private static extern object OpenApiDocumentProviderCtor( IServiceProvider serviceProvider );
}
+ // this class cannot use UnsafeAccessor or UnsafeAccessorType because it is generic and neither the class nor the
+ // type parameter is known at compile time
public static class NamedService
{
private static readonly Func factory = NewFactory();
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Property.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Property.cs
index b8c7cec0..ca239519 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Property.cs
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Property.cs
@@ -3,28 +3,17 @@
namespace Asp.Versioning.OpenApi.Reflection;
using Microsoft.AspNetCore.OpenApi;
-using static System.Linq.Expressions.Expression;
-using static System.Reflection.BindingFlags;
+using System.Runtime.CompilerServices;
// HACK: all of these properties are internal in Microsoft.AspNetCore.OpenApi
// REF: https://github.com/dotnet/aspnetcore/tree/main/src/OpenApi/src
internal static class Property
{
- private static readonly Action setDocumentName = NewSetDocumentName();
-
extension( OpenApiOptions options )
{
- public void SetDocumentName( string value ) => setDocumentName( options, value );
+ public void SetDocumentName( string value ) => SetDocumentNameImpl( options, value );
}
- private static Action NewSetDocumentName()
- {
- var options = Parameter( typeof( OpenApiOptions ), "options" );
- var documentName = Parameter( typeof( string ), "documentName" );
- var property = typeof( OpenApiOptions ).GetProperty( nameof( OpenApiOptions.DocumentName ), Instance | NonPublic | Public )!;
- var body = Assign( Property( options, property ), documentName );
- var lambda = Lambda>( body, options, documentName );
-
- return lambda.Compile();
- }
+ [UnsafeAccessor( UnsafeAccessorKind.Method, Name = "set_DocumentName" )]
+ private static extern void SetDocumentNameImpl( OpenApiOptions options, string value );
}
\ No newline at end of file
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Type.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Type.cs
index 14e85ea8..a4310614 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Type.cs
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Reflection/Type.cs
@@ -9,19 +9,29 @@ namespace Asp.Versioning.OpenApi.Reflection;
internal static class Type
{
[DynamicallyAccessedMembers( PublicConstructors )]
- public static readonly System.Type IDocumentProvider = System.Type.GetType( "Microsoft.Extensions.ApiDescriptions.IDocumentProvider, Microsoft.AspNetCore.OpenApi", throwOnError: true )!;
+ public static readonly System.Type IDocumentProvider = System.Type.GetType( Name.IDocumentProvider, throwOnError: true )!;
[DynamicallyAccessedMembers( PublicConstructors )]
- public static readonly System.Type NamedService = System.Type.GetType( "Microsoft.AspNetCore.OpenApi.NamedService`1[[Microsoft.AspNetCore.OpenApi.OpenApiDocumentService, Microsoft.AspNetCore.OpenApi]], Microsoft.AspNetCore.OpenApi", throwOnError: true )!;
+ public static readonly System.Type NamedService = System.Type.GetType( Name.NamedService, throwOnError: true )!;
- public static readonly System.Type IEnumerableOfNamedService = System.Type.GetType( "System.Collections.Generic.IEnumerable`1[[Microsoft.AspNetCore.OpenApi.NamedService`1[[Microsoft.AspNetCore.OpenApi.OpenApiDocumentService, Microsoft.AspNetCore.OpenApi]], Microsoft.AspNetCore.OpenApi]], System.Private.CoreLib", throwOnError: true )!;
+ public static readonly System.Type IEnumerableOfNamedService = System.Type.GetType( Name.IEnumerableOfNamedService, throwOnError: true )!;
[DynamicallyAccessedMembers( PublicConstructors )]
- public static readonly System.Type OpenApiDocumentProvider = System.Type.GetType( "Microsoft.Extensions.ApiDescriptions.OpenApiDocumentProvider, Microsoft.AspNetCore.OpenApi", throwOnError: true )!;
+ public static readonly System.Type OpenApiDocumentProvider = System.Type.GetType( Name.OpenApiDocumentProvider, throwOnError: true )!;
[DynamicallyAccessedMembers( PublicConstructors )]
- public static readonly System.Type OpenApiDocumentService = System.Type.GetType( "Microsoft.AspNetCore.OpenApi.OpenApiDocumentService, Microsoft.AspNetCore.OpenApi", throwOnError: true )!;
+ public static readonly System.Type OpenApiDocumentService = System.Type.GetType( Name.OpenApiDocumentService, throwOnError: true )!;
[DynamicallyAccessedMembers( PublicConstructors )]
- public static readonly System.Type OpenApiSchemaService = System.Type.GetType( "Microsoft.AspNetCore.OpenApi.OpenApiSchemaService, Microsoft.AspNetCore.OpenApi", throwOnError: true )!;
+ public static readonly System.Type OpenApiSchemaService = System.Type.GetType( Name.OpenApiSchemaService, throwOnError: true )!;
+
+ public static class Name
+ {
+ public const string IDocumentProvider = "Microsoft.Extensions.ApiDescriptions.IDocumentProvider, Microsoft.AspNetCore.OpenApi";
+ public const string NamedService = "Microsoft.AspNetCore.OpenApi.NamedService`1[[Microsoft.AspNetCore.OpenApi.OpenApiDocumentService, Microsoft.AspNetCore.OpenApi]], Microsoft.AspNetCore.OpenApi";
+ public const string IEnumerableOfNamedService = "System.Collections.Generic.IEnumerable`1[[Microsoft.AspNetCore.OpenApi.NamedService`1[[Microsoft.AspNetCore.OpenApi.OpenApiDocumentService, Microsoft.AspNetCore.OpenApi]], Microsoft.AspNetCore.OpenApi]], System.Private.CoreLib";
+ public const string OpenApiDocumentProvider = "Microsoft.Extensions.ApiDescriptions.OpenApiDocumentProvider, Microsoft.AspNetCore.OpenApi";
+ public const string OpenApiDocumentService = "Microsoft.AspNetCore.OpenApi.OpenApiDocumentService, Microsoft.AspNetCore.OpenApi";
+ public const string OpenApiSchemaService = "Microsoft.AspNetCore.OpenApi.OpenApiSchemaService, Microsoft.AspNetCore.OpenApi";
+ }
}
\ No newline at end of file
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/ReleaseNotes.txt b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/ReleaseNotes.txt
index 5f282702..c91871c9 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/ReleaseNotes.txt
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/ReleaseNotes.txt
@@ -1 +1,2 @@
-
\ No newline at end of file
+Clip dependent package version because the next major version is incompatible [dotnet/aspnetcore#67930](https://github.com/dotnet/aspnetcore/issues/67930)
+Fix `` summaries [Issue #1189](https://github.com/dotnet/aspnet-api-versioning/issues/1189)
\ No newline at end of file
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Transformers/XmlComments.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Transformers/XmlComments.cs
index 9601301a..915ada04 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Transformers/XmlComments.cs
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.OpenApi/Transformers/XmlComments.cs
@@ -8,6 +8,7 @@ namespace Asp.Versioning.OpenApi.Transformers;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
+using static System.Reflection.BindingFlags;
///
/// Provides access to XML documentation comments, which enables the retrieval of summaries, remarks, return values,
@@ -189,7 +190,7 @@ public virtual string GetResponseDescription( MemberInfo member, string statusCo
{
var element = GetMemberById( XmlCommentsProvider.GetDocumentationMemberId( member ) );
- // The C# compiler writes verbatim into the XML file; following it is the consumer's
+ // The compiler writes verbatim into the XML file; following it is the consumer's
// responsibility. Resolve it so members documented on a base type or an implemented interface still
// surface their summary, remarks, parameters, and so on.
if ( depth < MaxInheritDocDepth && element?.Element( "inheritdoc" ) is { } inheritdoc )
@@ -270,7 +271,7 @@ private static IEnumerable GetInheritedMembers( MemberInfo member )
[UnconditionalSuppressMessage( "ILLink", "IL2070" )]
private static MemberInfo? FindMatchingMember( Type type, MemberInfo member )
{
- const BindingFlags Flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
+ const BindingFlags Flags = Public | NonPublic | Instance | Static;
switch ( member )
{
diff --git a/src/AspNetCore/WebApi/test/Asp.Versioning.Http.Tests/DependencyInjection/IServiceCollectionExtensionsTest.cs b/src/AspNetCore/WebApi/test/Asp.Versioning.Http.Tests/DependencyInjection/IServiceCollectionExtensionsTest.cs
index 8e7f2219..bd22841d 100644
--- a/src/AspNetCore/WebApi/test/Asp.Versioning.Http.Tests/DependencyInjection/IServiceCollectionExtensionsTest.cs
+++ b/src/AspNetCore/WebApi/test/Asp.Versioning.Http.Tests/DependencyInjection/IServiceCollectionExtensionsTest.cs
@@ -27,34 +27,27 @@ public void add_api_versioning_should_not_allow_default_neutral_api_version()
options.Should().Throw();
}
- // REF: https://github.com/dotnet/aspnet-api-versioning/issues/1191
[Fact]
public void add_api_versioning_should_not_displace_or_wrap_user_registered_problem_details_writers()
{
// arrange
var services = new ServiceCollection();
- var customWriter = new TestProblemDetailsWriter();
+ var writer = new Mock();
+ writer.Setup( w => w.CanWrite( It.IsAny() ) ).Returns( true );
services.AddProblemDetails();
- services.AddSingleton( customWriter );
+ services.AddSingleton( writer.Object );
- var writersBefore = services.Where( s => s.ServiceType == typeof( IProblemDetailsWriter ) ).ToArray();
+ var before = services.Where( s => s.ServiceType == typeof( IProblemDetailsWriter ) ).ToArray();
// act
services.AddApiVersioning();
// assert
- var writersAfter = services.Where( s => s.ServiceType == typeof( IProblemDetailsWriter ) ).ToArray();
- writersAfter.Should().Equal( writersBefore );
-
+ var after = services.Where( s => s.ServiceType == typeof( IProblemDetailsWriter ) ).ToArray();
using var provider = services.BuildServiceProvider();
- provider.GetServices().Should().Contain( customWriter );
- }
-
- private sealed class TestProblemDetailsWriter : IProblemDetailsWriter
- {
- public bool CanWrite( ProblemDetailsContext context ) => true;
- public ValueTask WriteAsync( ProblemDetailsContext context ) => ValueTask.CompletedTask;
+ after.Should().Equal( before );
+ provider.GetServices().Should().Contain( writer.Object );
}
}
\ No newline at end of file