为swagger增加枚举说明支持
This commit is contained in:
parent
48c6d1299c
commit
baff3035e8
|
@ -12,20 +12,18 @@ namespace Falcon.SugarApi.ApiDefinistions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ApiResponseTypeModelProvider : IApplicationModelProvider
|
public class ApiResponseTypeModelProvider : IApplicationModelProvider
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
public int Order => 1;
|
public int Order => 1;
|
||||||
|
|
||||||
public void OnProvidersExecuted(ApplicationModelProviderContext context)
|
/// <inheritdoc/>
|
||||||
{
|
public void OnProvidersExecuted(ApplicationModelProviderContext context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnProvidersExecuting(ApplicationModelProviderContext context)
|
/// <inheritdoc/>
|
||||||
{
|
public void OnProvidersExecuting(ApplicationModelProviderContext context) {
|
||||||
foreach (ControllerModel controller in context.Result.Controllers)
|
foreach (ControllerModel controller in context.Result.Controllers) {
|
||||||
{
|
foreach (ActionModel action in controller.Actions) {
|
||||||
foreach (ActionModel action in controller.Actions)
|
if (!isApiAction(action)) {
|
||||||
{
|
|
||||||
if (!isApiAction(action))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var art = action.ActionMethod.ReturnType;
|
var art = action.ActionMethod.ReturnType;
|
||||||
|
@ -43,14 +41,11 @@ namespace Falcon.SugarApi.ApiDefinistions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="am">Action模型</param>
|
/// <param name="am">Action模型</param>
|
||||||
/// <returns>是api方法返回true,否则false</returns>
|
/// <returns>是api方法返回true,否则false</returns>
|
||||||
protected static bool isApiAction(ActionModel am)
|
protected static bool isApiAction(ActionModel am) {
|
||||||
{
|
if (am.Controller.Attributes.Any(c => c is ApiControllerAttribute)) {
|
||||||
if (am.Controller.Attributes.Any(c => c is ApiControllerAttribute))
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (am.Attributes.Any(c => c is ApiControllerAttribute))
|
if (am.Attributes.Any(c => c is ApiControllerAttribute)) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||||
<PackageReference Include="SqlSugarCore" Version="5.0.6.1" />
|
<PackageReference Include="SqlSugarCore" Version="5.0.6.1" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.6.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net5' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net5' ">
|
||||||
|
|
19
Falcon.SugarApi/Swagger/Readme.md
Normal file
19
Falcon.SugarApi/Swagger/Readme.md
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
22
Falcon.SugarApi/Swagger/SwaggerGenOptionsExtend.cs
Normal file
22
Falcon.SugarApi/Swagger/SwaggerGenOptionsExtend.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
|
||||||
|
namespace Falcon.SugarApi.Swagger
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SwaggerGenOptions扩展
|
||||||
|
/// </summary>
|
||||||
|
public static class SwaggerGenOptionsExtend
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 增加xml文件枚举说明支持
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">SwaggerGenOptions选项</param>
|
||||||
|
/// <param name="xmlPath">XML文件路径</param>
|
||||||
|
/// <returns>SwaggerGenOptions</returns>
|
||||||
|
public static SwaggerGenOptions AddXmlEnumEnable(this SwaggerGenOptions options,string xmlPath) {
|
||||||
|
options.DocumentFilter<SwaggerXmlEnumFilter>(xmlPath);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
Falcon.SugarApi/Swagger/SwaggerXmlEnumFilter.cs
Normal file
93
Falcon.SugarApi/Swagger/SwaggerXmlEnumFilter.cs
Normal file
|
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 通过DescriptionAttribute和summary生成枚举说明
|
||||||
|
/// </summary>
|
||||||
|
public class SwaggerXmlEnumFilter:IDocumentFilter
|
||||||
|
{
|
||||||
|
private readonly XPathNavigator _xmlNavigator;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存放程序集中的所有枚举类型
|
||||||
|
/// </summary>
|
||||||
|
public static List<Type> AllTypes { get; set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过提供应用程序文档生成枚举说明
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="xmlPath"></param>
|
||||||
|
public SwaggerXmlEnumFilter(string xmlPath) {
|
||||||
|
_xmlNavigator = new XPathDocument(xmlPath).CreateNavigator();
|
||||||
|
|
||||||
|
AllTypes = AllTypes ?? GetEnumTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化程序集中所有枚举类型
|
||||||
|
/// </summary>
|
||||||
|
public virtual List<Type> GetEnumTypes() {
|
||||||
|
var types = new List<Type>();
|
||||||
|
foreach(var ass in AppDomain.CurrentDomain.GetAssemblies()) {
|
||||||
|
types.AddRange(ass.GetTypes().Where(m => m.IsEnum));
|
||||||
|
}
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 对文档进行初拉力
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="swaggerDoc"></param>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
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<OpenApiInteger>();
|
||||||
|
foreach(var val in property.Enum) {
|
||||||
|
list.Add((OpenApiInteger)val);
|
||||||
|
}
|
||||||
|
property.Description += describeEnum(itemType,list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string describeEnum(Type type,List<OpenApiInteger> enums) {
|
||||||
|
var enumDescriptions = new List<string>();
|
||||||
|
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 $"<br/>{Environment.NewLine}{string.Join("<br/>" + 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<DescriptionAttribute>()) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,6 +92,10 @@ namespace Falcon.SugarApi.XmlSerialize
|
||||||
#endregion
|
#endregion
|
||||||
#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放占用资源
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"></param>
|
||||||
protected override void Dispose(bool disposing) {
|
protected override void Dispose(bool disposing) {
|
||||||
if (disposing) {
|
if (disposing) {
|
||||||
this.BaseWriter.Dispose();
|
this.BaseWriter.Dispose();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user