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

  • Biwen.QuickApi代码生成器功能上线已关闭评论
  • 109 次浏览
  • A+
所属分类:.NET技术
摘要

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

 [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 交流 ~