• AspNetCore 生成接口文档


    获取所有继承自 ControllerBase 的类,获取其公共的实例的方法(不包含父类),认作接口,

    接口注释的xml文件,可以在项目-右键属性-生成-XML文档文件勾选,再次生成。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Http;
    using System.Reflection;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Xml;
    
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Hosting;
    
    /*
        // Install-Package System.Text.Encoding.CodePages
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
    
        // BackgroundService
        services.AddHostedService<GenerateApiDocumentService>();
         
     */
    namespace App.HostServices
    {
        /// <summary>
        /// 生成接口文档
        /// </summary>
        public class GenerateApiDocumentService : BackgroundService
        {
            /// <summary>生成的Csv路径</summary>
            public static string CSVPath = "d:/1.csv";
            /// <summary>当前提供的接口生成的注释路径</summary>
            public static string AnnotationXmlPath = "d:/API.xml";
    
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="stoppingToken"></param>
            /// <returns></returns>
            protected override async Task ExecuteAsync(CancellationToken stoppingToken)
            {
                var doc = new XmlDocument();
                doc.Load(AnnotationXmlPath);
                var xpath = "/doc/members/member";
                var nodes = doc.SelectNodes(xpath).Cast<XmlNode>().ToList();
    
                var ass = Assembly.GetEntryAssembly();
                var types = ass.GetTypes();
    
                var cbt = typeof(ControllerBase);
    
                var ls = new List<MM>();
                foreach (var type in types)
                {
                    if (!cbt.IsAssignableFrom(type)) continue;
    
                    // 过滤一些
                    if (type.FullName.StartsWith("Microsoft.AspNetCore.Mvc")) continue;
                    if (type.Name.EqualIgnoreCase("BaseController")) continue;
    
                    var publicMethods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
                    if (!publicMethods.Any()) continue;
    
                    foreach (var method in publicMethods)
                    {
                        var attrs = method.GetCustomAttributes().ToList();
    
                        var httpMethod = HttpMethod.Get;
                        if (attrs.Any(d => d.GetType() == typeof(HttpPostAttribute)))
                        {
                            httpMethod = HttpMethod.Post;
                        }
    
                        var methodParas = new List<String>();
                        // 参数
                        var paras = method.GetParameters();
                        foreach (var para in paras)
                        {
                            methodParas.Add($"{para.ParameterType.Name} {para.Name}");
                        }
    
                        var summary = getSummary(nodes, type.FullName, method.Name, paras.Length > 0);
                        var mm = new MM()
                        {
                            ControllerName = type.Name,
                            ActionName = method.Name,
                            HttpMethod = httpMethod,
                            Summary = summary,
    
                            Attrs = attrs.Select(d => d.GetType().Name).ToList(),
                            Paras = methodParas,
                        };
    
                        ls.Add(mm);
                    }
    
                }
    
                ToFile(CSVPath, ls);
    
                await Task.CompletedTask;
            }
    
            static void ToFile(String path, List<MM> ls)
            {
                File.Delete(path);
    
                var defEncoding = Encoding.GetEncoding("gb2312");
                using (var fs = File.OpenWrite(path))
                {
                    {
                        var headerStr = "ControllerName,ActionName,Summary,Paras,HttpMethod,Attrs
    ";
                        var data = defEncoding.GetBytes(headerStr);
                        fs.Write(data);
                    }
    
                    foreach (var item in ls)
                    {
                        {
                            var rowStr = $"{item.ControllerName},{item.ActionName}," +
                                $"{item.Summary}," +
                                $"{item.Paras.Join(" ")}," +
                                $"{item.HttpMethod},{item.Attrs.Join("/")}
    ";
                            var data = defEncoding.GetBytes(rowStr);
                            fs.Write(data);
                        }
                    }
                }
            }
    
            // 获取方法注释
            static String getSummary(IList<XmlNode> nodes, String typeFullName, String methodName, bool hasParas)
            {
                /*
                     <member name="M:System.on(System.String)">
                         <summary>创建新的User</summary>
                         <param name="token"></param>
                         <returns></returns>
                     </member>
                */
                // M:API.Common.TokenSession.CreateSession(
                var name = $"M:{typeFullName}.{methodName}{(hasParas ? "(" : "")}";
    
                foreach (var node in nodes)
                {
                    var attrs = node.Attributes;
                    foreach (XmlAttribute attr in attrs)
                    {
                        if (attr.Name.EqualIgnoreCase("name"))
                        {
                            var attrVal = attr.Value;
                            if (attrVal.StartsWithIgnoreCase(name))
                            {
                                // 读取 summary
                                var summary = node.ChildNodes.Cast<XmlNode>().FirstOrDefault(d => d.Name.EqualIgnoreCase("summary"));
    
                                return summary?.InnerText;
                            }
                        }
    
                    }
                }
    
                return null;
            }
    
        }
    
        /// <summary></summary>
        public class MM
        {
            public String ControllerName { get; set; }
            public String ActionName { get; set; }
    
            public HttpMethod HttpMethod { get; set; }
    
            /// <summary>注释</summary>
            public String Summary { get; set; }
    
            public IList<String> Attrs { get; set; }
    
            public IList<String> Paras { get; set; }
    
        }
    
    
    }
    

      

  • 相关阅读:
    图解SSH隧道功能
    su和sudo命令的用法
    Linux下下载百度网盘资料
    WPS Office 2019 for Linux来了
    Linux下的录屏软件Kazam
    用hdparm获取硬盘参数
    百度,你能不能有点节操?
    locate的基本用法
    Java class不分32位和64位
    Web站点抓取工具webhttrack
  • 原文地址:https://www.cnblogs.com/huawublog/p/14705242.html
Copyright © 2020-2023  润新知