Skip to content

Commit 33f5dba

Browse files
authored
feat:Support public properties in MinimalAPIs (#554)
* feat: Support public properties in MinimalAPIs * feat: Support public properties in MinimalAPIs * fix: Fix unit test errors * chore: Optimize unit test duration * chore: Fix code smell
1 parent 435de40 commit 33f5dba

File tree

7 files changed

+131
-24
lines changed

7 files changed

+131
-24
lines changed

src/Contrib/Data/IdGenerator/Snowflake/Tests/Masa.Contrib.Data.IdGenerator.Snowflake.Distributed.Redis.Tests/IdGeneratorTest.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ public async Task TestGetWorkerIdAsync()
233233
[TestMethod]
234234
public async Task TestGetDistibutedLockFaieldAsync()
235235
{
236-
var workerIdBits = 10;
236+
var workerIdBits = 2;
237237
var maxWorkerId = ~(-1L << workerIdBits);
238238
var tasks = new ConcurrentBag<Task>();
239239
ThreadPool.GetMinThreads(out int workerThreads, out var minIoc);
@@ -242,7 +242,7 @@ public async Task TestGetDistibutedLockFaieldAsync()
242242
int laterTime = 0;
243243
try
244244
{
245-
Parallel.For(0, maxWorkerId * 2, _ =>
245+
Parallel.For(0, maxWorkerId * 10, _ =>
246246
{
247247
tasks.Add(GetWorkerIdAsync(null, workerIdBits));
248248
});

src/Contrib/Service/Masa.Contrib.Service.MinimalAPIs/Helpers/ServiceBaseHelper.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ public static Delegate CreateDelegate(MethodInfo methodInfo, object targetInstan
99
{
1010
var type = Expression.GetDelegateType(methodInfo.GetParameters().Select(parameterInfo => parameterInfo.ParameterType)
1111
.Concat(new List<Type>
12-
{ methodInfo.ReturnType }).ToArray());
12+
{
13+
methodInfo.ReturnType
14+
}).ToArray());
1315
return Delegate.CreateDelegate(type, targetInstance, methodInfo);
1416
}
1517

@@ -24,7 +26,7 @@ public static string ParseMethodPrefix(IEnumerable<string> prefixes, string meth
2426
var prefix = prefixes.FirstOrDefault(prefix => newMethodName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
2527

2628
if (prefix is not null)
27-
return prefix;
29+
return methodName.Substring(0, prefix.Length);
2830

2931
return string.Empty;
3032
}

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

+32-10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public abstract class ServiceBase : IService
2828

2929
public IServiceCollection Services => MasaApp.GetServices();
3030

31+
private bool? _enableProperty;
32+
3133
#pragma warning disable S4136
3234
protected ServiceBase() { }
3335

@@ -50,14 +52,7 @@ protected virtual IServiceProvider GetServiceProvider()
5052

5153
internal void AutoMapRoute(ServiceGlobalRouteOptions globalOptions, PluralizationService pluralizationService)
5254
{
53-
var type = GetType();
54-
55-
var methodInfos = type
56-
.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
57-
.Where(methodInfo => methodInfo.CustomAttributes.All(attr => attr.AttributeType != typeof(IgnoreRouteAttribute)))
58-
.Concat(type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
59-
.Where(methodInfo => methodInfo.CustomAttributes.Any(attr => attr.AttributeType == typeof(RoutePatternAttribute))))
60-
.Distinct();
55+
var methodInfos = GetMethodsByAutoMapRoute(GetType(), globalOptions);
6156

6257
foreach (var method in methodInfos)
6358
{
@@ -92,6 +87,25 @@ internal void AutoMapRoute(ServiceGlobalRouteOptions globalOptions, Pluralizatio
9287
}
9388
}
9489

90+
protected virtual List<MethodInfo> GetMethodsByAutoMapRoute(Type type, ServiceGlobalRouteOptions globalOptions)
91+
{
92+
var bindingFlags = BindingFlags.Public | BindingFlags.Instance;
93+
var methodInfos = type
94+
.GetMethods(BindingFlags.DeclaredOnly | bindingFlags)
95+
.Where(methodInfo => methodInfo.CustomAttributes.All(attr => attr.AttributeType != typeof(IgnoreRouteAttribute)))
96+
.Concat(type.GetMethods(bindingFlags)
97+
.Where(methodInfo => methodInfo.CustomAttributes.Any(attr => attr.AttributeType == typeof(RoutePatternAttribute))))
98+
.Distinct();
99+
_enableProperty = RouteOptions.EnableProperty ?? globalOptions.EnableProperty ?? false;
100+
if (!_enableProperty.Value)
101+
{
102+
return methodInfos.Where(methodInfo => !methodInfo.IsSpecialName).ToList();
103+
}
104+
105+
return methodInfos.Where(methodInfo
106+
=> !methodInfo.IsSpecialName || (methodInfo.IsSpecialName && methodInfo.Name.StartsWith("get_"))).ToList();
107+
}
108+
95109
protected virtual string GetBaseUri(ServiceRouteOptions globalOptions, PluralizationService pluralizationService)
96110
{
97111
if (!string.IsNullOrWhiteSpace(BaseUri))
@@ -112,7 +126,10 @@ protected virtual string GetBaseUri(ServiceRouteOptions globalOptions, Pluraliza
112126
RouteHandlerBuilder MapMethods(ServiceRouteOptions globalOptions, string pattern, string? httpMethod, Delegate handler)
113127
{
114128
if (!string.IsNullOrWhiteSpace(httpMethod))
115-
return App.MapMethods(pattern, new[] { httpMethod }, handler);
129+
return App.MapMethods(pattern, new[]
130+
{
131+
httpMethod
132+
}, handler);
116133

117134
var httpMethods = GetDefaultHttpMethods(globalOptions);
118135
if (httpMethods.Length > 0)
@@ -173,7 +190,12 @@ string TrimMethodPrefix(string name)
173190

174191
protected virtual (string? HttpMethod, string Prefix) ParseMethod(ServiceRouteOptions globalOptions, string methodName)
175192
{
176-
var prefix = ServiceBaseHelper.ParseMethodPrefix(RouteOptions.GetPrefixes ?? globalOptions.GetPrefixes!, methodName);
193+
var getPrefixes = RouteOptions.GetPrefixes ?? globalOptions.GetPrefixes!;
194+
if (_enableProperty!.Value)
195+
{
196+
getPrefixes.Insert(0, "get_");
197+
}
198+
var prefix = ServiceBaseHelper.ParseMethodPrefix(getPrefixes, methodName);
177199
if (!string.IsNullOrEmpty(prefix))
178200
return ("GET", prefix);
179201

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

+1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ public ServiceGlobalRouteOptions()
2525
DisableTrimMethodPrefix = false;
2626
Assemblies = MasaApp.GetAssemblies();
2727
Pluralization = PluralizationService.CreateService(CultureInfo.CreateSpecificCulture("en"));
28+
EnableProperty = false;
2829
}
2930
}

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

+6
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,10 @@ public class ServiceRouteOptions
4242
/// When the collection is empty, the default Post, Get, Put, Delete all support access
4343
/// </summary>
4444
public string[] MapHttpMethodsForUnmatched { get; set; } = Array.Empty<string>();
45+
46+
/// <summary>
47+
/// Enable access to public properties
48+
/// default: false
49+
/// </summary>
50+
public bool? EnableProperty { get; set; }
4551
}

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

+39-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ namespace Masa.Contrib.Service.MinimalAPIs.Tests;
66
[TestClass]
77
public class ServiceBaseTest
88
{
9+
private static FieldInfo _enablePropertyFieldInfo
10+
=> typeof(ServiceBase).GetField("_enableProperty", BindingFlags.Instance | BindingFlags.NonPublic)!;
11+
912
[TestMethod]
1013
public void TestGetBaseUri()
1114
{
@@ -40,9 +43,7 @@ public void TestCombineUris()
4043
{
4144
var uris = new[]
4245
{
43-
"api",
44-
"v1",
45-
"order"
46+
"api", "v1", "order"
4647
};
4748
Assert.AreEqual("api/v1/order", ServiceBaseHelper.CombineUris(uris));
4849
}
@@ -154,18 +155,26 @@ public void TestConstructor()
154155
}
155156

156157
[DataTestMethod]
157-
[DataRow("AddUser", "POST", "Add")]
158-
[DataRow("PostUser", "POST", "Post")]
159-
[DataRow("DeleteUser", "DELETE", "Delete")]
160-
[DataRow("PutUser", "PUT", "Put")]
161-
[DataRow("GetUser", "GET", "Get")]
162-
[DataRow("AuditState", null, "")]
158+
[DataRow("AddUser", "POST", "Add", false)]
159+
[DataRow("PostUser", "POST", "Post", false)]
160+
[DataRow("DeleteUser", "DELETE", "Delete", false)]
161+
[DataRow("PutUser", "PUT", "Put", false)]
162+
[DataRow("GetUser", "GET", "Get", false)]
163+
[DataRow("get_Name", "GET", "get", false)]
164+
[DataRow("get_Name", "GET", "get_", true)]
165+
[DataRow("set_Name", null, "", false)]
166+
[DataRow("set_Name", null, "", true)]
167+
[DataRow("AuditState", null, "", false)]
163168
public void TestParseMethod(
164169
string methodName,
165170
string? actualHttpMethod,
166-
string actualPrefix)
171+
string actualPrefix,
172+
bool enableProperty)
167173
{
168174
var service = new UserService();
175+
176+
_enablePropertyFieldInfo.SetValue(service, enableProperty);
177+
169178
var globalOptions = new ServiceGlobalRouteOptions();
170179
var result = service.TestParseMethod(globalOptions, methodName);
171180
Assert.AreEqual(actualHttpMethod, result.HttpMethod);
@@ -202,6 +211,26 @@ public void TestGetServiceName(bool enablePluralizeServiceName, string actualSer
202211
Assert.AreEqual("Catalogs", service.TestGetServiceName(pluralizationService));
203212
}
204213

214+
[DataTestMethod]
215+
[DataRow(true, true, 2)]
216+
[DataRow(true, false, 1)]
217+
[DataRow(true, null, 2)]
218+
[DataRow(null, true, 2)]
219+
[DataRow(null, false, 1)]
220+
[DataRow(null, null, 1)]
221+
[DataRow(false, true, 2)]
222+
[DataRow(false, false, 1)]
223+
[DataRow(false, null, 1)]
224+
public void TestGetMethodsByAutoMapRoute(bool? globalEnableProperty, bool? enableProperty, int expectedNumber)
225+
{
226+
var orderService = new OrderService(enableProperty);
227+
var methodInfos = orderService.TestGetMethodsByAutoMapRoute(new ServiceGlobalRouteOptions()
228+
{
229+
EnableProperty = globalEnableProperty
230+
});
231+
Assert.AreEqual(expectedNumber, methodInfos.Count);
232+
}
233+
205234
#region private methods
206235

207236
private static CustomServiceBase GetCustomService()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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+
namespace Masa.Contrib.Service.MinimalAPIs.Tests.Services;
5+
6+
#pragma warning disable CA1822
7+
public class OrderService : ServiceBase
8+
{
9+
public string ConnectionString => GetConnectionString;
10+
11+
public static string GetConnectionString => "connection string";
12+
13+
public int Id { private get; set; }
14+
15+
private int Age { get; set; }
16+
17+
public int CreateTime;
18+
19+
public OrderService() : base()
20+
{
21+
22+
}
23+
24+
public OrderService(bool? enableProperty)
25+
{
26+
RouteOptions.EnableProperty = enableProperty;
27+
}
28+
29+
private static string GetName() => "name";
30+
31+
public static void SetName()
32+
{
33+
34+
}
35+
36+
public override string ToString()
37+
{
38+
return nameof(OrderService);
39+
}
40+
41+
[IgnoreRoute]
42+
public List<MethodInfo> TestGetMethodsByAutoMapRoute(ServiceGlobalRouteOptions globalOptions)
43+
{
44+
return base.GetMethodsByAutoMapRoute(typeof(OrderService), globalOptions);
45+
}
46+
}
47+
#pragma warning restore CA1822

0 commit comments

Comments
 (0)