Skip to content

Commit 539524a

Browse files
committed
feat(MinimalAPIs): Support AddMasaMinimalAPIs
1 parent 7ceecc3 commit 539524a

File tree

6 files changed

+130
-2
lines changed

6 files changed

+130
-2
lines changed

src/Contrib/Service/Masa.Contrib.Service.MinimalAPIs/Extensions/ServiceCollectionExtensions.cs

+35
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,41 @@ public static WebApplication AddServices(
6262
return app;
6363
}
6464

65+
public static IServiceCollection AddMasaMinimalAPIs(
66+
this IServiceCollection services,
67+
Action<ServiceGlobalRouteOptions>? action = null)
68+
{
69+
if (services.All(service => service.ImplementationType != typeof(MinimalApisMarkerService)))
70+
{
71+
services.AddSingleton<MinimalApisMarkerService>();
72+
73+
services.AddHttpContextAccessor();
74+
if (action == null)
75+
{
76+
services.Configure<ServiceGlobalRouteOptions>(_ =>
77+
{
78+
79+
});
80+
}
81+
else
82+
{
83+
services.Configure(action);
84+
}
85+
86+
MasaApp.TrySetServiceCollection(services);
87+
var serviceProvider = services.BuildServiceProvider();
88+
var serviceMapOptions = serviceProvider.GetRequiredService<IOptions<ServiceGlobalRouteOptions>>().Value;
89+
var serviceTypes = TypeHelper.GetServiceTypes<ServiceBase>(serviceMapOptions.Assemblies.ToArray());
90+
foreach (var serviceType in serviceTypes)
91+
{
92+
GlobalMinimalApiOptions.AddService(serviceType);
93+
services.AddSingleton(serviceType);
94+
}
95+
}
96+
97+
return services;
98+
}
99+
65100
private sealed class MinimalApisMarkerService
66101
{
67102

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) MASA Stack All rights reserved.
2+
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3+
4+
// ReSharper disable once CheckNamespace
5+
6+
namespace Microsoft.AspNetCore.Builder;
7+
8+
public static class WebApplicationExtensions
9+
{
10+
public static void MapMasaMinimalAPIs(this WebApplication webApplication)
11+
{
12+
MasaApp.Build(webApplication.Services);
13+
GlobalMinimalApiOptions.WebApplication = webApplication;
14+
15+
var serviceMapOptions = webApplication.Services.GetRequiredService<IOptions<ServiceGlobalRouteOptions>>().Value;
16+
foreach (var serviceType in GlobalMinimalApiOptions.ServiceTypes)
17+
{
18+
var serviceInstance = (ServiceBase)webApplication.Services.GetRequiredService(serviceType);
19+
if (serviceInstance.RouteOptions.DisableAutoMapRoute ?? serviceMapOptions.DisableAutoMapRoute ?? false)
20+
return;
21+
22+
serviceInstance.AutoMapRoute(serviceMapOptions, serviceMapOptions.Pluralization);
23+
}
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) MASA Stack All rights reserved.
2+
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3+
4+
// ReSharper disable once CheckNamespace
5+
6+
namespace Masa.Contrib.Service.MinimalAPIs;
7+
8+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
9+
internal static class GlobalMinimalApiOptions
10+
{
11+
#pragma warning disable S2223
12+
public static WebApplication? WebApplication;
13+
#pragma warning restore S2223
14+
public static List<Type> ServiceTypes { get; private set; } = new();
15+
16+
public static void AddService(Type serviceType)
17+
{
18+
if (ServiceTypes.Contains(serviceType))
19+
return;
20+
21+
ServiceTypes.Add(serviceType);
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) MASA Stack All rights reserved.
2+
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3+
4+
// ReSharper disable once CheckNamespace
5+
6+
namespace Masa.Contrib.Service.MinimalAPIs;
7+
8+
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
9+
internal static class TypeHelper
10+
{
11+
public static IEnumerable<Type> GetServiceTypes<TService>(params Assembly[] assemblies)
12+
where TService : class
13+
=> from type in assemblies.SelectMany(assembly => assembly.GetTypes())
14+
where !type.IsAbstract && BaseOf<TService>(type)
15+
select type;
16+
17+
private static bool BaseOf<T>(Type type)
18+
{
19+
if (type.BaseType == typeof(T)) return true;
20+
21+
return type.BaseType != null && BaseOf<T>(type.BaseType);
22+
}
23+
}

src/Contrib/Service/Masa.Contrib.Service.MinimalAPIs/ServiceBase.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

4+
// ReSharper disable once CheckNamespace
5+
46
namespace Microsoft.AspNetCore.Builder;
57

68
public abstract class ServiceBase : IService
79
{
8-
public WebApplication App => MasaApp.GetRequiredService<WebApplication>();
10+
private WebApplication? _webApplication;
11+
12+
public WebApplication App => _webApplication ??= GlobalMinimalApiOptions.WebApplication ?? MasaApp.GetRequiredService<WebApplication>();
913

1014
public string BaseUri { get; init; }
1115

src/Contrib/Service/Tests/Masa.Contrib.Service.MinimalAPIs.Tests/MinimalAPITest.cs

+19-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ public void TestAddMultiServices()
2727
public void AddService()
2828
{
2929
var app = _builder.AddServices();
30-
Assert.IsTrue(_builder.Services.Any(service => service.ServiceType == typeof(CustomService) && service.Lifetime == ServiceLifetime.Scoped));
30+
Assert.IsTrue(_builder.Services.Any(service
31+
=> service.ServiceType == typeof(CustomService) && service.Lifetime == ServiceLifetime.Scoped));
3132

3233
var servicePrvider = _builder.Services.BuildServiceProvider();
3334
var customService = servicePrvider.GetService<CustomService>();
@@ -46,4 +47,21 @@ public void AddService()
4647

4748
Assert.IsTrue(newCustomService.GetTest2() == 1);
4849
}
50+
51+
[TestMethod]
52+
public void TestMapMasaMinimalAPIs()
53+
{
54+
_builder.Services.AddMasaMinimalAPIs();
55+
Assert.IsTrue(_builder.Services.Any<CatalogService>());
56+
Assert.IsTrue(_builder.Services.Any<CustomService>());
57+
Assert.IsTrue(_builder.Services.Any<GoodsService>());
58+
Assert.IsTrue(_builder.Services.Any<UserService>());
59+
60+
var app = _builder.Build();
61+
62+
app.MapMasaMinimalAPIs();
63+
64+
var service = (ServiceBase)app.Services.GetRequiredService(typeof(CatalogService));
65+
Assert.AreEqual(app, service.App);
66+
}
4967
}

0 commit comments

Comments
 (0)