<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用 .NET6 打造動態(tài) API

          共 4287字,需瀏覽 9分鐘

           ·

          2021-12-15 01:02


          前言


          ApiLite是直接將Service層自動生成api路由,可以不用添加Controller,支持模塊插件化,在項目開發(fā)中能夠提高工作效率,降低代碼量。


          開發(fā)環(huán)境

          • .NET SDK 6.0.100-rc.2.21505.57
          • VS2022 Preview 7.0

          地址

          • GitHub: https://github.com/known/ApiLite

          目標

          • 根據(jù)Service動態(tài)生成api
          • 支持自定義路由模板(通過Route特性定義)
          • 支持模塊插件化
          • 支持不同模塊,相同Service名稱的路由(命名空間需要有3級以上,例如:Com.Mod.XXX)
          • 自動根據(jù)方法名稱判斷請求方式,Get開頭的方法名為GET請求,其他為POST請求

          編碼約定

          • 模塊類庫必須包含繼承IModule接口的類
          • 需要生成api的Service必須繼承IService接口
          • GET請求的方法必須以Get開頭

          核心代碼

          主要是ApiFeatureProvider和ApiConvention這兩個自定義類來動態(tài)生成api,ApiFeatureProvider繼承ControllerFeatureProvider,覆寫IsController方法,判斷服務(wù)類型是否符合Controller。

          ApiConvention實現(xiàn)了IApplicationModelConvention接口,動態(tài)添加Action。

          下面是主要代碼,完整代碼請在GitHub上下載。

          static?class?ServiceExtension
          {
          ????internal?static?WebApplicationBuilder?AddKApp(this?WebApplicationBuilder?builder,?Action??action?=?null)
          ????{
          ????????var?option?=?new?AppOption();
          ????????action?.Invoke(option);
          ????????...
          ????????AddDynamicApi(mvcBuilder,?option);//添加動態(tài)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,這樣才能發(fā)現(xiàn)服務(wù)類
          ????????????????var?assembly?=?item.GetType().Assembly;
          ????????????????m.ApplicationParts.Add(new?AssemblyPart(assembly));
          ????????????}
          ????????????m.FeatureProviders.Add(new?ApiFeatureProvider());
          ????????});

          ????????builder.Services.Configure(o?=>
          ????????{
          ????????????o.Conventions.Add(new?ApiConvention());
          ????????});
          ????}

          ????internal?static?WebApplication?UseKApp(this?WebApplication?app)
          ????{
          ????????...
          ????????return?app;
          ????}
          }

          //判斷服務(wù)類型是否為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);
          ????????????}
          ????????}
          ????}

          ????...

          ????//構(gòu)造路由模板
          ????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;
          ????}
          }


          轉(zhuǎn)自:known

          鏈接:cnblogs.com/known/p/15499542.html

          瀏覽 66
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成年视频在线 | 操逼大片。| а√天堂资源官网在线资源 | 久热中文在线观看精品视频 | 国产黄色一级 |