Skip to content

Commit

Permalink
Refactor DI so that IApiVersionDescriptionProviderFactory creates IAp…
Browse files Browse the repository at this point in the history
…iVersionDescriptionProvider in all paths and can be the single source of replacement
  • Loading branch information
commonsensesoftware committed Mar 26, 2024
1 parent 5039854 commit a227703
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.

#pragma warning disable SA1135 // Using directives should be qualified
#pragma warning disable SA1200 // Using directives should be placed correctly

using Asp.Versioning;
using Asp.Versioning.ApiExplorer;
using Microsoft.Extensions.Options;
#pragma warning disable CA1812 // Avoid uninstantiated internal classes

namespace Microsoft.AspNetCore.Builder;

using Asp.Versioning;
using Asp.Versioning.ApiExplorer;
using Microsoft.AspNetCore.Routing;
using Activator = Func<IEnumerable<IApiVersionMetadataCollationProvider>, ISunsetPolicyManager, IOptions<ApiExplorerOptions>, IApiVersionDescriptionProvider>;
using Microsoft.Extensions.Options;

internal sealed class ApiVersionDescriptionProviderFactory : IApiVersionDescriptionProviderFactory
{
private readonly ISunsetPolicyManager sunsetPolicyManager;
private readonly IApiVersionMetadataCollationProvider[] providers;
private readonly IEndpointInspector endpointInspector;
private readonly IOptions<ApiExplorerOptions> options;
private readonly Activator activator;

public ApiVersionDescriptionProviderFactory(
Activator activator,
ISunsetPolicyManager sunsetPolicyManager,
IEnumerable<IApiVersionMetadataCollationProvider> providers,
IEndpointInspector endpointInspector,
IOptions<ApiExplorerOptions> options )
{
this.activator = activator;
this.sunsetPolicyManager = sunsetPolicyManager;
this.providers = providers.ToArray();
this.endpointInspector = endpointInspector;
Expand All @@ -43,6 +37,6 @@ public IApiVersionDescriptionProvider Create( EndpointDataSource endpointDataSou

collators.AddRange( providers );

return activator( collators, sunsetPolicyManager, options );
return new DefaultApiVersionDescriptionProvider( collators, sunsetPolicyManager, options );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ namespace Microsoft.Extensions.DependencyInjection;
using Asp.Versioning;
using Asp.Versioning.ApiExplorer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using static ServiceDescriptor;

/// <summary>
Expand Down Expand Up @@ -54,54 +52,17 @@ private static void AddApiExplorerServices( IApiVersioningBuilder builder )

services.AddMvcCore().AddApiExplorer();
services.TryAddSingleton<IOptionsFactory<ApiExplorerOptions>, ApiExplorerOptionsFactory<ApiExplorerOptions>>();
services.TryAddTransient( ResolveApiVersionDescriptionProviderFactory );
services.TryAddSingleton( ResolveApiVersionDescriptionProvider );
services.TryAddTransient<IApiVersionDescriptionProviderFactory, ApiVersionDescriptionProviderFactory>();
services.TryAddSingleton( static sp => sp.GetRequiredService<IApiVersionDescriptionProviderFactory>().Create() );

// use internal constructor until ASP.NET Core fixes their bug
// BUG: https://github.com/dotnet/aspnetcore/issues/41773
services.TryAddEnumerable(
Transient<IApiDescriptionProvider, VersionedApiDescriptionProvider>(
sp => new(
static sp => new(
sp.GetRequiredService<ISunsetPolicyManager>(),
sp.GetRequiredService<IModelMetadataProvider>(),
sp.GetRequiredService<IInlineConstraintResolver>(),
sp.GetRequiredService<IOptions<ApiExplorerOptions>>() ) ) );
}

private static IApiVersionDescriptionProviderFactory ResolveApiVersionDescriptionProviderFactory( IServiceProvider serviceProvider )
{
var sunsetPolicyManager = serviceProvider.GetRequiredService<ISunsetPolicyManager>();
var providers = serviceProvider.GetServices<IApiVersionMetadataCollationProvider>();
var inspector = serviceProvider.GetRequiredService<IEndpointInspector>();
var options = serviceProvider.GetRequiredService<IOptions<ApiExplorerOptions>>();

return new ApiVersionDescriptionProviderFactory(
NewDefaultProvider,
sunsetPolicyManager,
providers,
inspector,
options );

static DefaultApiVersionDescriptionProvider NewDefaultProvider(
IEnumerable<IApiVersionMetadataCollationProvider> providers,
ISunsetPolicyManager sunsetPolicyManager,
IOptions<ApiExplorerOptions> apiExplorerOptions ) =>
new( providers, sunsetPolicyManager, apiExplorerOptions );
}

private static IApiVersionDescriptionProvider ResolveApiVersionDescriptionProvider( IServiceProvider serviceProvider )
{
var factory = serviceProvider.GetRequiredService<IApiVersionDescriptionProviderFactory>();
var endpointDataSource = new EmptyEndpointDataSource();
return factory.Create( endpointDataSource );
}

private sealed class EmptyEndpointDataSource : EndpointDataSource
{
public override IReadOnlyList<Endpoint> Endpoints => Array.Empty<Endpoint>();

public override IChangeToken GetChangeToken() => new CancellationChangeToken( CancellationToken.None );

public override IReadOnlyList<Endpoint> GetGroupedEndpoints( RouteGroupContext context ) => Array.Empty<Endpoint>();
}
}

0 comments on commit a227703

Please sign in to comment.