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; } } } } } } }