using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Xml.XPath;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace FAuth.Extensions
{
///
/// 通过DescriptionAttribute和summary生成枚举说明
///
public class SwaggerXmlEnumFilter:IDocumentFilter
{
private readonly XPathNavigator _xmlNavigator;
public static List AllTypes { get; set; }
///
/// 通过提供应用程序文档生成枚举说明
///
///
public SwaggerXmlEnumFilter(string xmlPath) {
_xmlNavigator = new XPathDocument(xmlPath).CreateNavigator();
if(AllTypes == null) {
AllTypes = new List();
foreach(var ass in AppDomain.CurrentDomain.GetAssemblies()) {
AllTypes.AddRange(ass.GetTypes().Where(m => m.IsEnum));
}
}
}
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.ToString()}:{Enum.GetName(type,value)}; ");
else
enumDescriptions.Add($"{item.Value.ToString()}:{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;
}
}
}