使用.NET6实现动态API
2022/6/4 23:20:27
本文主要是介绍使用.NET6实现动态API,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
ApiLite是基于.NET6直接将Service层生成动态api路由,可以不用添加Controller,支持模块插件化,在项目开发中能够提高工作效率,降低代码量。
开发环境
- .NET SDK 6.0.100-rc.2.21505.57
- VS2022 Preview 7.0
项目地址
- GitHub: https://github.com/known/ApiLite
项目目标
- 根据Service动态生成api
- 支持自定义路由模板(通过Route特性定义)
- 支持模块插件化
- 支持不同模块,相同Service名称的路由(命名空间需要有3级以上,例如:Com.Mod.XXX)
- 自动根据方法名称判断请求方式,Get开头的方法名为GET请求,其他为POST请求
编码约定
- 模块类库必须包含继承IModule接口的类
- 需要生成api的Service必须继承IService接口
- GET请求的方法必须以Get开头
核心代码
主要是ApiFeatureProvider和ApiConvention这两个自定义类来动态生成api,ApiFeatureProvider继承ControllerFeatureProvider,覆写IsController方法,判断服务类型是否符合Controller。ApiConvention实现了IApplicationModelConvention接口,实现动态添加Action。下面是主要代码,完整代码请在GitHub上下载。
static class ServiceExtension { internal static WebApplicationBuilder AddKApp(this WebApplicationBuilder builder, Action<AppOption>? action = null) { var option = new AppOption(); action?.Invoke(option); ... AddDynamicApi(mvcBuilder, option);//添加动态api return builder; } private static void AddDynamicApi(IMvcBuilder builder, AppOption option) { builder.ConfigureApplicationPartManager(m => { m.ApplicationParts.Add(new AssemblyPart(typeof(IService).Assembly)); foreach (var item in option.Modules) { item.Initialize();//初始化模块 //将模块添加到ApplicationParts,这样才能发现服务类 var assembly = item.GetType().Assembly; m.ApplicationParts.Add(new AssemblyPart(assembly)); } m.FeatureProviders.Add(new ApiFeatureProvider()); }); builder.Services.Configure<MvcOptions>(o => { o.Conventions.Add(new ApiConvention()); }); } } //判断服务类型是否为Controller class ApiFeatureProvider : ControllerFeatureProvider { protected override bool IsController(TypeInfo typeInfo) { if (!typeof(IService).IsAssignableFrom(typeInfo) || !typeInfo.IsPublic || typeInfo.IsAbstract || typeInfo.IsGenericType) return false; return true; } } class ApiConvention : IApplicationModelConvention { public void Apply(ApplicationModel application) { foreach (var controller in application.Controllers) { var type = controller.ControllerType; if (typeof(IService).IsAssignableFrom(type)) { ConfigureApiExplorer(controller); ConfigureSelector(controller); } } } ... //构造路由模板 private string GetRouteTemplate(ActionModel action) { if (action.Attributes != null && action.Attributes.Count > 0) { foreach (var item in action.Attributes) { if (item is RouteAttribute attribute) { return attribute.Path;//返回自定义路由 } } } var routeTemplate = new StringBuilder(); //routeTemplate.Append("api"); var names = action.Controller.ControllerType.Namespace.Split('.'); if (names.Length > 2) { //支持不同模块相同类名,添加命名空间模块名作前缀 routeTemplate.Append(names[^2]); } // Controller var controllerName = action.Controller.ControllerName; if (controllerName.EndsWith("Service")) controllerName = controllerName[0..^7]; routeTemplate.Append($"/{controllerName}"); // Action var actionName = action.ActionName; if (actionName.EndsWith("Async")) actionName = actionName[..^"Async".Length]; if (!string.IsNullOrEmpty(actionName)) routeTemplate.Append($"/{actionName}"); return routeTemplate.ToString(); } }
使用示例
KHost.Run(args, o => { o.Modules.Add(new TestModule());//添加模块 }); class TestModule : IModule { public void Initialize() { } } public class TestService : IService { public string GetName(string name) { return $"Hello {name}"; } public string SaveData(string data) { return $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {data}"; } [Route("api/test")] public string GetCustMethod(string id) { return id; } }
原文链接:https://www.cnblogs.com/known/p/15499542.html
这篇关于使用.NET6实现动态API的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-11-18微软研究:RAG系统的四个层次提升理解与回答能力
- 2024-11-15C#中怎么从PEM格式的证书中提取公钥?-icode9专业技术文章分享
- 2024-11-14云架构设计——如何用diagrams.net绘制专业的AWS架构图?
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#
- 2024-01-24Advanced .Net Debugging 1:你必须知道的调试工具