我正在使用 Swagger API 文档,并希望在文档中包含我对枚举的描述。我正在使用自定义过滤器使用注释从类和枚举中提取信息。 例如:
using System.ComponentModel;
...
[DisplayName("Upload class")] // Works fine
public class Upload
{
[DisplayName("Primary Key")] // Works fine
public int UploadMetaId { get; set; }
[Display(Name = "document name")] // Works fine too
public string Title { get; set; }
}
但是我的枚举有问题:
[DisplayName("Document types")] // Illegal, gives error CS0592
// or
[Display(Name = "Document types")] // Illegal too, gives also CS0592
public enum UploadType
{
[Display(Name = "Årsopgørelse")] // Works fine
PartnerAarsopgoerelse = 1,
[Display(Name = "Ægtefælles årsopgørelse")]
AegtefaelleAarsopgoerelse = 2
}
错误 CS0592 表示它在此声明类型上无效。
那么我可以用什么来代替呢?
更新
我正在使用以下 NuGet 包:
感谢@ralf 和他评论中的文章,我使用自己的 IDocumentFilter 创建了一个解决方案。
我希望我可以通过使用下面的代码来帮助某人进行大量搜索。
我在program.cs中从项目中获取XML文档并将相关的“摘要”传递给IDocumentFilter:
private static void ConfigureServices(IServiceCollection services)
{
...
services.AddSwaggerGen(c =>
{
...
Dictionary<string, string> Dict = new Dictionary<string, string>();
var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (var filePath in System.IO.Directory.GetFiles(dir, "*.xml"))
{
c.IncludeXmlComments(filePath);
GetXMLDoc(filePath, Dict);
}
c.DocumentFilter<SwaggerEnumDocumentFilter>(Dict);
});
}
private static void GetXMLDoc(string path, Dictionary<string,string> Dict)
{
var _xmlComments = new XmlDocument();
var reader = XmlReader.Create(path);
_xmlComments.Load(reader);
var xpath = $"//member[@name[starts-with(.,'F')] or @name[starts-with(.,'T')]]";
var nodes = _xmlComments.DocumentElement.SelectNodes(xpath);
foreach(XmlNode node in nodes)
{
var attribute = node.Attributes["name"];
if (attribute != null)
{
string summary = node.FirstChild.InnerText.Trim(' ','\n');
Dict.Add(attribute.Value, summary);
}
}
}
在过滤器中,我从传递的字典中选取 XML 文档:
public class SwaggerEnumDocumentFilter : IDocumentFilter
{
Dictionary<string, string> EnumDescription = new Dictionary<string, string>();
public SwaggerEnumDocumentFilter(Dictionary<string, string> enumDescription)
{
EnumDescription = enumDescription;
}
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
// add enum descriptions Schemas section in Swagger
foreach (var property in swaggerDoc.Components.Schemas)
{
var propertyEnums = property.Value.Enum;
if (propertyEnums is { Count: > 0 })
{
property.Value.Description += DescribeEnum(property.Key, false);
}
}
if (swaggerDoc.Paths.Count <= 0)
{
return;
}
//add enum descriptions to input parameters
foreach (var pathItem in swaggerDoc.Paths.Values)
{
foreach (var operation in pathItem.Operations)
{
if (operation.Value.Parameters != null)
{
foreach (var param in operation.Value.Parameters)
{
if (param.Schema.Reference != null)
{
param.Description += DescribeEnum(param.Schema.Reference.Id, true);
}
}
}
}
}
}
private Type GetEnumTypeByName(string enumTypeName)
{
if (string.IsNullOrEmpty(enumTypeName))
{
return null;
}
try
{
return AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Single(x => x.FullName != null && x.Name == enumTypeName);
}
catch (InvalidOperationException e)
{
throw new Exception($"SwaggerDoc: Can not find a unique Enum for specified typeName '{enumTypeName}'. Please provide a more unique enum name.");
}
}
private string DescribeEnum(string propertyTypeName, bool inApiList)
{
var enumType = GetEnumTypeByName(propertyTypeName);
if (enumType == null)
{
return null;
}
var values = Enum.GetValues(enumType);
if (values == null)
{
return null;
}
string result = "<ul>";
if (inApiList)
{
var key = $"T:{enumType.FullName}";
var summary = EnumDescription.ContainsKey(key) ? EnumDescription[key] : "";
result = $"<p>{summary}</p><ul>";
}
foreach (var value in values)
{
var key = $"F:{enumType.FullName}.{value}";
var summary = EnumDescription.ContainsKey(key) ? EnumDescription[key] : "";
string n = EnumUtils.GetDisplayName((System.Enum)value);
result += $"<li>{(int)value} - {n} : {summary} </li>";
}
result += "</ul>";
return result;
}
}