using Swashbuckle.Swagger;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
namespace HH.WCS.Mobox3.DSZSH {
///
/// Swagger 显示控制器的描述
///
public class SwaggerCacheProvider : ISwaggerProvider
{
private readonly ISwaggerProvider _swaggerProvider;
private static ConcurrentDictionary _cache = new ConcurrentDictionary();
private readonly string _xmlPath;
///
///
///
///
/// xml文档路径
public SwaggerCacheProvider(ISwaggerProvider swaggerProvider, string xmlpath)
{
_swaggerProvider = swaggerProvider;
_xmlPath = xmlpath;
}
public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
{
var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
// 只读取一次
if (!_cache.TryGetValue(cacheKey, out SwaggerDocument srcDoc))
{
srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
srcDoc.vendorExtensions = new Dictionary
{
{ "ControllerDesc", GetControllerDesc() }
};
_cache.TryAdd(cacheKey, srcDoc);
}
return srcDoc;
}
///
/// 从API文档中读取控制器描述
///
/// 所有控制器描述
public ConcurrentDictionary GetControllerDesc()
{
ConcurrentDictionary controllerDescDict = new ConcurrentDictionary();
if (File.Exists(_xmlPath))
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(_xmlPath);
string[] arrPath;
int cCount = "Controller".Length;
foreach (XmlNode node in xmldoc.SelectNodes("//member"))
{
string type = node.Attributes["name"].Value;
if (type.StartsWith("T:"))
{
arrPath = type.Split('.');
string controllerName = arrPath[arrPath.Length - 1];
if (controllerName.EndsWith("Controller")) // 控制器
{
// 获取控制器注释
XmlNode summaryNode = node.SelectSingleNode("summary");
string key = controllerName.Remove(controllerName.Length - cCount, cCount);
if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
{
controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
}
}
}
}
}
return controllerDescDict;
}
}
///
/// 增强版Swagger提供程序,支持显示控制器和模型的完整文档注释
///
public class EnhancedSwaggerCacheProvider : ISwaggerProvider {
private readonly ISwaggerProvider _swaggerProvider;
private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary();
private readonly string _xmlPath;
public EnhancedSwaggerCacheProvider(ISwaggerProvider swaggerProvider, string xmlpath) {
_swaggerProvider = swaggerProvider;
_xmlPath = xmlpath;
}
public SwaggerDocument GetSwagger(string rootUrl, string apiVersion) {
var cacheKey = $"{rootUrl}_{apiVersion}";
return _cache.GetOrAdd(cacheKey, _ =>
{
var srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
// 添加控制器描述
var (controllerDesc, modelDesc) = GetXmlComments();
srcDoc.vendorExtensions = new Dictionary
{
{ "ControllerDesc", controllerDesc },
{ "ModelDesc", modelDesc }
};
// 为模型添加描述
EnhanceModelDescriptions(srcDoc, modelDesc);
return srcDoc;
});
}
///
/// 从XML文档中提取控制器和模型描述
///
private (ConcurrentDictionary controllerDesc,
ConcurrentDictionary modelDesc) GetXmlComments() {
var controllerDesc = new ConcurrentDictionary();
var modelDesc = new ConcurrentDictionary();
if (!File.Exists(_xmlPath)) return (controllerDesc, modelDesc);
var xmldoc = new XmlDocument();
xmldoc.Load(_xmlPath);
foreach (XmlNode node in xmldoc.SelectNodes("//member")) {
var type = node.Attributes?["name"]?.Value;
if (string.IsNullOrEmpty(type)) continue;
if (type.StartsWith("T:")) {
var arrPath = type.Split('.');
var typeName = arrPath[arrPath.Length - 1]; // 获取最后一部分
// 处理控制器
if (typeName.EndsWith("Controller")) {
var summaryNode = node.SelectSingleNode("summary");
if (summaryNode != null && !string.IsNullOrWhiteSpace(summaryNode.InnerText)) {
//var key = typeName[..^"Controller".Length];
string key = typeName;
const string controllerSuffix = "Controller";
if (typeName.EndsWith(controllerSuffix)) {
key = typeName.Substring(0, typeName.Length - controllerSuffix.Length);
}
controllerDesc.TryAdd(key, summaryNode.InnerText.Trim());
}
}
// 处理模型类
else if (IsModelType(node)) {
var summaryNode = node.SelectSingleNode("summary");
if (summaryNode != null && !string.IsNullOrWhiteSpace(summaryNode.InnerText)) {
modelDesc.TryAdd(typeName, summaryNode.InnerText.Trim());
}
// 处理模型属性
EnhancePropertyDescriptions(node, modelDesc);
}
}
}
return (controllerDesc, modelDesc);
}
///
/// 判断是否为模型类型
///
private bool IsModelType(XmlNode node) {
// 这里可以根据实际需求调整判断逻辑
// 例如:排除Controller、排除特定命名空间等
var type = node.Attributes?["name"]?.Value ?? "";
return type.StartsWith("T:") &&
!type.EndsWith("Controller") &&
!type.Contains(".Controllers.") &&
!type.Contains(".Infrastructure.");
}
///
/// 增强模型属性的描述
///
private void EnhancePropertyDescriptions(XmlNode typeNode, ConcurrentDictionary modelDesc) {
var typeName = typeNode.Attributes?["name"]?.Value?.Split('.')?.LastOrDefault()?.Substring(2);
if (string.IsNullOrEmpty(typeName)) return;
foreach (XmlNode propNode in typeNode.SelectNodes("field|property")) {
var propName = propNode.Attributes?["name"]?.Value;
if (string.IsNullOrEmpty(propName)) continue;
var summaryNode = propNode.SelectSingleNode("summary");
var exampleNode = propNode.SelectSingleNode("example");
if (summaryNode != null && !string.IsNullOrWhiteSpace(summaryNode.InnerText)) {
var fullPropKey = $"{typeName}.{propName}";
var description = summaryNode.InnerText.Trim();
if (exampleNode != null && !string.IsNullOrWhiteSpace(exampleNode.InnerText)) {
description += $"\n\n示例: {exampleNode.InnerText.Trim()}";
}
modelDesc.TryAdd(fullPropKey, description);
}
}
}
///
/// 增强Swagger文档中的模型描述
///
private void EnhanceModelDescriptions(SwaggerDocument swaggerDoc, ConcurrentDictionary modelDesc) {
if (swaggerDoc.definitions == null) return;
foreach (var definition in swaggerDoc.definitions) {
// 处理模型类本身描述
if (modelDesc.TryGetValue(definition.Key, out var classDesc)) {
definition.Value.description = classDesc;
}
// 处理模型属性描述
if (definition.Value.properties != null) {
foreach (var property in definition.Value.properties) {
var fullPropKey = $"{definition.Key}.{property.Key}";
if (modelDesc.TryGetValue(fullPropKey, out var propDesc)) {
property.Value.description = propDesc;
}
}
}
}
}
}
}