{} 使用方式 : dotnet add package Biwen.QuickApi dotnet add package Biwen.QuickApi.Sour" />

Biwen.QuickApi代码生成器功能上线

biwen,quickapi,代码,生成器,功能,上线 · 浏览次数 : 34

小编点评

**Biwen.QuickApi 代码生成器的核心概念** * 基于反射查找所有标记 [QuickApi] 特征的 API。 * 批量注册服务并映射路由。 * 使用 SourceGen 代码生成器提升代码性能。 **关键代码** ```csharp var req = await ((dynamic)api).ReqBinder.BindAsync(ctx.HttpContext!); // 验证请求参数 try { var result = await method.Invoke(api, new object[] { req! })!; // 返回响应结果 } catch (Exception ex) { // 捕获异常并处理异常 } ``` **主要概念** * **反射查找**:根据 API 中的标记查找所有 `[QuickApi]` 属性的 API。 * **代码生成器**:使用 `SourceGen` 类自动生成 API 代码。 * **性能提升**:通过使用 SourceGen 代码生成器优化代码,提升性能。 * **路由映射**:将路由映射到 API 中的特定方法。

正文


[QuickApi("hello/world")]
public class MyApi : BaseQuickApi<Req,Rsp>{}

使用方式 :

 dotnet add package Biwen.QuickApi
 dotnet add package Biwen.QuickApi.SourceGenerator

最后简简单单注册路由:

app.MapGenQuickApis("api");

Biwen.QuickApi 使用REPR风格写的minimalApi已经写完了, 最近看到道友们都玩SourceGen提升代码性能
,所以一鼓作气 自己也实现了一个 Biwen.QuickApi的 代码生成器版本 用以替换 代码中反射和dynamic带来的性能问题

Biwen.QuickApi下面这一段核心代码:

            var req = await ((dynamic)api).ReqBinder.BindAsync(ctx.HttpContext!);
            //验证DTO
           if (req.RealValidator.Validate(req) is ValidationResult vresult && !vresult!.IsValid)
             {
                return Results.ValidationProblem(vresult.ToDictionary());
              }
            try
            {
                //var result = await method.Invoke(api, new object[] { req! })!;
                var result = await ((dynamic)api)!.ExecuteAsync(req!);
                if (result is EmptyResponse)
                {
                    return Results.Ok();
                }
                if (result is ContentResponse content)
                {
                    return Results.Content(content.Content);
                }
                Func<dynamic?, dynamic?> rspToExpandoObject = (rsp) =>
                {
                    if (rsp == null) return null;
                    var type = rsp.GetType() as Type;
                    var hasAlias = type!.GetProperties().Any(x => x.GetCustomAttribute<AliasAsAttribute>() != null);
                    if (!hasAlias)
                    {
                        return rsp;
                    }
                    dynamic expandoObject = new ExpandoObject();
                    foreach (var prop in type.GetProperties())
                    {
                        var alias = prop.GetCustomAttribute<AliasAsAttribute>();
                        ((IDictionary<string, object>)expandoObject)[alias != null ? alias.Name : prop.Name] = prop.GetValue(rsp);
                    }
                    return expandoObject;
                };
                var expandoResult = rspToExpandoObject(result);
                return Results.Json(expandoResult, quickApiOptions?.JsonSerializerOptions);
            }
            catch (Exception ex)
            {
                var exceptionHandlers = ctx.HttpContext!.RequestServices.GetServices<IQuickApiExceptionHandler>();
                //异常处理
                foreach (var handler in exceptionHandlers)
                {
                    await handler.HandleAsync(ex);
                }
                //默认处理
                throw;
            }

Biwen.QuickApi的原理就是反射查找所有标记[QuickApi]特征的Api,然后批量注册服务&批量映射路由. 路由请求执行的方法体使用了上面那一段可能性能堪忧的代码. 如果用Gen的方式那么 上面一段代码就都变成了强类型引用 生成如下的结果 :


//绑定对象
var req = await api.ReqBinder.BindAsync(ctx.HttpContext!);
//验证器
if (req.RealValidator.Validate(req) is ValidationResult vresult && !vresult!.IsValid)
{
	return Results.ValidationProblem(vresult.ToDictionary());
}
//执行请求
try
{
	var result = await api.ExecuteAsync(req!);
	return Results.Json(result);
}
catch (Exception ex)
{
	var exceptionHandlers = ctx.HttpContext!.RequestServices.GetServices<IQuickApiExceptionHandler>();
	//异常处理
	foreach (var handler in exceptionHandlers)
	{
		await handler.HandleAsync(ex);
	}
	//默认处理
	throw;
}
```这个就爽歪歪了 反射的问题没有了 动态类型也不见了 性能直接提升了 !

最后 Gen的实现代码可以翻看.
https://github.com/vipwan/Biwen.QuickApi 这里就不赘述了. 

欢迎 star 交流 ~ 

与Biwen.QuickApi代码生成器功能上线相似的内容: