From baff3035e8bc3951ac603dafc2a72386cbed69c4 Mon Sep 17 00:00:00 2001 From: falcon <9504402@qq.com> Date: Tue, 19 Apr 2022 10:45:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAswagger=E5=A2=9E=E5=8A=A0=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E8=AF=B4=E6=98=8E=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApiResponseTypeModelProvider.cs | 27 +++--- Falcon.SugarApi/Falcon.SugarApi.csproj | 1 + Falcon.SugarApi/Swagger/Readme.md | 19 ++++ .../Swagger/SwaggerGenOptionsExtend.cs | 22 +++++ .../Swagger/SwaggerXmlEnumFilter.cs | 93 +++++++++++++++++++ Falcon.SugarApi/XmlSerialize/MyXmlWriter.cs | 4 + 6 files changed, 150 insertions(+), 16 deletions(-) create mode 100644 Falcon.SugarApi/Swagger/Readme.md create mode 100644 Falcon.SugarApi/Swagger/SwaggerGenOptionsExtend.cs create mode 100644 Falcon.SugarApi/Swagger/SwaggerXmlEnumFilter.cs diff --git a/Falcon.SugarApi/ApiDefinistions/ApiResponseTypeModelProvider.cs b/Falcon.SugarApi/ApiDefinistions/ApiResponseTypeModelProvider.cs index 8f38acb..917cf0e 100644 --- a/Falcon.SugarApi/ApiDefinistions/ApiResponseTypeModelProvider.cs +++ b/Falcon.SugarApi/ApiDefinistions/ApiResponseTypeModelProvider.cs @@ -12,20 +12,18 @@ namespace Falcon.SugarApi.ApiDefinistions /// public class ApiResponseTypeModelProvider : IApplicationModelProvider { + /// public int Order => 1; - public void OnProvidersExecuted(ApplicationModelProviderContext context) - { + /// + public void OnProvidersExecuted(ApplicationModelProviderContext context) { } - public void OnProvidersExecuting(ApplicationModelProviderContext context) - { - foreach (ControllerModel controller in context.Result.Controllers) - { - foreach (ActionModel action in controller.Actions) - { - if (!isApiAction(action)) - { + /// + public void OnProvidersExecuting(ApplicationModelProviderContext context) { + foreach (ControllerModel controller in context.Result.Controllers) { + foreach (ActionModel action in controller.Actions) { + if (!isApiAction(action)) { continue; } var art = action.ActionMethod.ReturnType; @@ -43,14 +41,11 @@ namespace Falcon.SugarApi.ApiDefinistions /// /// Action模型 /// 是api方法返回true,否则false - protected static bool isApiAction(ActionModel am) - { - if (am.Controller.Attributes.Any(c => c is ApiControllerAttribute)) - { + protected static bool isApiAction(ActionModel am) { + if (am.Controller.Attributes.Any(c => c is ApiControllerAttribute)) { return true; } - if (am.Attributes.Any(c => c is ApiControllerAttribute)) - { + if (am.Attributes.Any(c => c is ApiControllerAttribute)) { return true; } return false; diff --git a/Falcon.SugarApi/Falcon.SugarApi.csproj b/Falcon.SugarApi/Falcon.SugarApi.csproj index 4b476b3..1a63810 100644 --- a/Falcon.SugarApi/Falcon.SugarApi.csproj +++ b/Falcon.SugarApi/Falcon.SugarApi.csproj @@ -13,6 +13,7 @@ + diff --git a/Falcon.SugarApi/Swagger/Readme.md b/Falcon.SugarApi/Swagger/Readme.md new file mode 100644 index 0000000..9ebe84c --- /dev/null +++ b/Falcon.SugarApi/Swagger/Readme.md @@ -0,0 +1,19 @@ +## 使用SwaggerGenOptions.AddXmlEnumEnable方法可以为枚举类型增加matedata说明 + +```c# + //注册Swagger + services.AddSwaggerGen(c => { + //获取应用程序基础目录 + var basePath = AppContext.BaseDirectory; + //指定应用程序说明XML文件 + var xmlFile = new string[] { "ggws.Service.xml", "Ggws.Database.xml", "Falcon.SugarApi.xml" }; + foreach (var xf in xmlFile) { + var path = Path.Combine(basePath, xf); + //引入文件 + c.IncludeXmlComments(path, true); + //为枚举增加说明 + c.AddXmlEnumEnable(path); + } + }); + +``` \ No newline at end of file diff --git a/Falcon.SugarApi/Swagger/SwaggerGenOptionsExtend.cs b/Falcon.SugarApi/Swagger/SwaggerGenOptionsExtend.cs new file mode 100644 index 0000000..1b04f84 --- /dev/null +++ b/Falcon.SugarApi/Swagger/SwaggerGenOptionsExtend.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Falcon.SugarApi.Swagger +{ + /// + /// SwaggerGenOptions扩展 + /// + public static class SwaggerGenOptionsExtend + { + /// + /// 增加xml文件枚举说明支持 + /// + /// SwaggerGenOptions选项 + /// XML文件路径 + /// SwaggerGenOptions + public static SwaggerGenOptions AddXmlEnumEnable(this SwaggerGenOptions options,string xmlPath) { + options.DocumentFilter(xmlPath); + return options; + } + } +} diff --git a/Falcon.SugarApi/Swagger/SwaggerXmlEnumFilter.cs b/Falcon.SugarApi/Swagger/SwaggerXmlEnumFilter.cs new file mode 100644 index 0000000..4f72f1e --- /dev/null +++ b/Falcon.SugarApi/Swagger/SwaggerXmlEnumFilter.cs @@ -0,0 +1,93 @@ +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using System.Xml.XPath; + +namespace Falcon.SugarApi.Swagger +{ + /// + /// 通过DescriptionAttribute和summary生成枚举说明 + /// + public class SwaggerXmlEnumFilter:IDocumentFilter + { + private readonly XPathNavigator _xmlNavigator; + + /// + /// 存放程序集中的所有枚举类型 + /// + public static List AllTypes { get; set; } = null; + + /// + /// 通过提供应用程序文档生成枚举说明 + /// + /// + public SwaggerXmlEnumFilter(string xmlPath) { + _xmlNavigator = new XPathDocument(xmlPath).CreateNavigator(); + + AllTypes = AllTypes ?? GetEnumTypes(); + } + + /// + /// 初始化程序集中所有枚举类型 + /// + public virtual List GetEnumTypes() { + var types = new List(); + foreach(var ass in AppDomain.CurrentDomain.GetAssemblies()) { + types.AddRange(ass.GetTypes().Where(m => m.IsEnum)); + } + return types; + } + /// + /// 对文档进行初拉力 + /// + /// + /// + public void Apply(OpenApiDocument swaggerDoc,DocumentFilterContext context) { + var enumList = swaggerDoc.Components.Schemas.Where(m => m.Value.Enum != null && m.Value.Enum.Count > 0); + foreach(var item in enumList) { + var key = item.Key; + var property = item.Value; + var itemType = AllTypes.Find(m => m.Name == key); + var list = new List(); + foreach(var val in property.Enum) { + list.Add((OpenApiInteger)val); + } + property.Description += describeEnum(itemType,list); + } + } + + private string describeEnum(Type type,List enums) { + var enumDescriptions = new List(); + foreach(var item in enums) { + if(type == null) + continue; + var value = Enum.Parse(type,item.Value.ToString()); + var desc = getDescription(type,value); + + if(string.IsNullOrEmpty(desc)) + enumDescriptions.Add($"{item.Value}:{Enum.GetName(type,value)}; "); + else + enumDescriptions.Add($"{item.Value}:{Enum.GetName(type,value)},{desc}; "); + + } + return $"
{Environment.NewLine}{string.Join("
" + Environment.NewLine,enumDescriptions)}"; + } + + private string getDescription(Type t,object value) { + foreach(var member in t.GetMembers().Where(m => m.Name == t.GetEnumName(value))) { + foreach(var attr in member.GetCustomAttributes()) { + return attr.Description; + } + } + var fullName = $"{t.FullName}.{t.GetEnumName(value)}"; + var desc = _xmlNavigator.SelectSingleNode($"doc/members/member[@name='F:{fullName}']/summary")?.InnerXml; + return desc ?? string.Empty; + } + + } +} diff --git a/Falcon.SugarApi/XmlSerialize/MyXmlWriter.cs b/Falcon.SugarApi/XmlSerialize/MyXmlWriter.cs index 5998b88..64be3e5 100644 --- a/Falcon.SugarApi/XmlSerialize/MyXmlWriter.cs +++ b/Falcon.SugarApi/XmlSerialize/MyXmlWriter.cs @@ -92,6 +92,10 @@ namespace Falcon.SugarApi.XmlSerialize #endregion #pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释 + /// + /// 释放占用资源 + /// + /// protected override void Dispose(bool disposing) { if (disposing) { this.BaseWriter.Dispose();