zoukankan      html  css  js  c++  java
  • 利用反射生成接口列表

          公司产品对外公布的接口, 评审后才能发布, 然后要求生成接口文档(去除注释, 这样更能检查接口命名是否合理).

          之前用的是微软的一个免费工具, 但好久都没有更新了, 对新一点的C#语法不支持, 生成的文档是错误的, 如果不想手动从代码复制方法签名, 只能手写一个工具了

          这个段代码以满足公司要求来编写, 没有多余精力去优化代码了, 其中用到了扩展方法导致很多地方不合理. 但是总归不用手动写文档了, 避免了很多无意义的工作.

      

        // First: Install-Package NPOI
        using NPOI.XWPF.UserModel;
        using System;
        using System.Collections.Generic;
        using System.IO;
        using System.Linq;
        using System.Reflection;
    
        public static class InterfaceExportHelper
        {
            static BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Static;
    
            public static int spaceIncreaseCountOfEachLevel = 4;
            public static string CSharpClassColor = "2B93AF";
            public static string CSharpKeywordColor = "0000FF";
            public static bool IsShowParameterDefaultValue = false;
    
            public static void SeparateInterfaceToDocument(string assemblyPath, string outputDocPath)
            {
                var assembly = Assembly.LoadFrom(assemblyPath);
                var types = assembly.GetTypes().OrderBy(t => t.Name);
                XWPFDocument doc = new XWPFDocument();
                var spaceCount = 0;
                foreach (var type in types)
                {
                    if (type.IsClass)
                    {
                        var p = DealClass(type, doc, spaceCount);
                        if (p != null)
                        {
                            p.AppendCarriageReturn();
                        }
                    }
                    else if (type.IsEnum)
                    {
                        var p = DealEnum(type, doc, spaceCount);
                        if (p != null)
                        {
                            p.AppendCarriageReturn();
                        }
                    }
                    else if (type.IsValueType)
                    {
                        var p = DealStruct(type, doc, spaceCount);
                        if (p != null)
                        {
                            p.AppendCarriageReturn();
                        }
                    }
                }
    
                var fs = new FileStream(outputDocPath, FileMode.Create);
                doc.Write(fs);
                fs.Close();
            }
    
    
    
            static XWPFParagraph DealClass(Type type, XWPFDocument doc, int spaceCount)
            {
                if (!type.IsPublic)
                {
                    return null;
                }
                //if (type.IsNestedPrivate)
                //{
                //    return null;
                //}
                if (type.Name.StartsWith("<"))
                {
                    return null;
                }
                var p = doc.CreateParagraph();
                p.AppendSpaces(spaceCount);
                if (type.IsPublic)
                {
                    p.AppendKeywordCSharp("public");
                }
                else
                {
                    p.AppendKeywordCSharp("internal");
                }
                p.AppendSpaces();
    
                if (type.IsAbstract && type.IsSealed)
                {
                    p.AppendKeywordCSharp("static");
                    p.AppendSpaces();
                }
                else if (type.IsSealed)
                {
                    p.AppendKeywordCSharp("sealed");
                    p.AppendSpaces();
                }
                else if (type.IsAbstract)
                {
                    p.AppendKeywordCSharp("abstract");
                    p.AppendSpaces();
                }
    
                p.AppendKeywordCSharp("class");
                p.AppendSpaces();
                p.AppendClassCSharp(type.Name);
                bool hasBaseType = false;
                if (type.BaseType != null && type.BaseType != typeof(object))
                {
                    hasBaseType = true;
                    p.AppendText(" : ");
                    DispalyType(type.BaseType, p);
                }
                bool isFisrtInterface = true;
                foreach (var interfaceType in type.GetInterfaces())
                {
                    if (!hasBaseType)
                    {
                        p.AppendText(" : ");
                    }
                    if (!isFisrtInterface || hasBaseType)
                    {
                        p.AppendText(", ");
                    }
                    DispalyType(interfaceType, p);
                    isFisrtInterface = false;
                }
                p.AppendCarriageReturn();
    
                var tempSpaceCount = spaceCount;// - spaceIncreaseCountOfEachLevel > 0 ? spaceCount - spaceIncreaseCountOfEachLevel : 0;
                p.AppendSpaces(tempSpaceCount);
                p.AppendText("{");
                p.AppendCarriageReturn();
    
    
    
                bool hasAddedSomething = false;
                foreach (var filedInfo in type.GetFields(bindingFlags))
                {
                    if (!filedInfo.IsPublic && !filedInfo.IsFamily)
                    {
                        continue;
                    }
                    DealFieldInfo(filedInfo, p, spaceCount + spaceIncreaseCountOfEachLevel);
                    hasAddedSomething = true;
                }
                if (hasAddedSomething) p.AppendCarriageReturn();
    
    
    
    
                hasAddedSomething = false;
                foreach (ConstructorInfo constructorInfo in type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
                {
                    if (DealConstructor(constructorInfo, p, spaceCount + spaceIncreaseCountOfEachLevel) == true)
                    {
                        hasAddedSomething = true;
                    }
                }
                if (hasAddedSomething) p.AppendCarriageReturn();
    
    
    
                hasAddedSomething = false;
                foreach (var propertyInfo in type.GetProperties(bindingFlags))
                {
                    if (DealProperty(propertyInfo, p, spaceCount + spaceIncreaseCountOfEachLevel) == true)
                    {
                        hasAddedSomething = true;
                    }
                }
                if (hasAddedSomething) p.AppendCarriageReturn();
    
    
    
                hasAddedSomething = false;
                foreach (MethodInfo method in type.GetMethods(bindingFlags))
                {
                    if (DealMethod(method, p, spaceCount + spaceIncreaseCountOfEachLevel) == true)
                    {
                        hasAddedSomething = true;
                    }
                }
                if (hasAddedSomething) p.AppendCarriageReturn();
                p.RemoveRun(p.Runs.Count - 1);
                p.AppendSpaces(tempSpaceCount);
                p.AppendText("}");
                return p;
            }
    
            static bool DealFieldInfo(FieldInfo fieldInfo, XWPFParagraph p, int spaceCount)
            {
                if (!(fieldInfo.IsPublic || fieldInfo.IsFamily))
                {
                    return false;
                }
                //if (fieldInfo.IsPrivate)
                //{
                //    return false;
                //}
                p.AppendSpaces(spaceCount);
                var eventFieldList = new List<FieldInfo>();
    
                if (fieldInfo.IsPublic)
                {
                    p.AppendKeywordCSharp("public");
                }
                else if (fieldInfo.IsFamily)
                {
                    p.AppendKeywordCSharp("protected");
                }
                else if (fieldInfo.IsAssembly)
                {
                    p.AppendKeywordCSharp("internal");
                }
                else if (fieldInfo.IsFamilyOrAssembly)
                {
                    p.AppendKeywordCSharp("internal protected");
                }
                p.AppendSpaces();
    
                if (fieldInfo.IsInitOnly)
                {
                    p.AppendKeywordCSharp("readonly");
                    p.AppendSpaces();
                }
    
                if (fieldInfo.IsStatic)
                {
                    p.AppendKeywordCSharp("static");
                    p.AppendSpaces();
                }
    
                DispalyType(fieldInfo.FieldType, p);
                p.AppendSpaces();
    
                p.AppendText(fieldInfo.Name);
                p.AppendText(";");
                p.AppendCarriageReturn();
                return true;
            }
    
            static bool DealProperty(PropertyInfo propertyInfo, XWPFParagraph p, int spaceCount)
            {
                AccessorModifier? getterAccessorModifier = null, setterAccessorModifier = null;
                if (propertyInfo.CanRead)
                {
                    getterAccessorModifier = GetAccessorModifier(propertyInfo.GetMethod);
                }
                if (propertyInfo.CanWrite)
                {
                    setterAccessorModifier = GetAccessorModifier(propertyInfo.SetMethod);
                }
    
                var mainAccessorModifier = GetHighAccessorModifier(getterAccessorModifier, setterAccessorModifier);
    
                if (!(mainAccessorModifier == AccessorModifier.Public || mainAccessorModifier == AccessorModifier.Protected))
                {
                    return false;
                }
    
                p.AppendSpaces(spaceCount);
    
                p.AppendKeywordCSharp(AccessorModifierToString(mainAccessorModifier));
                p.AppendSpaces();
    
                DispalyType(propertyInfo.PropertyType, p);
                p.AppendSpaces();
    
                p.AppendText(propertyInfo.Name);
                p.AppendSpaces();
    
                p.AppendText("{");
                if (propertyInfo.CanRead && getterAccessorModifier >= AccessorModifier.Protected)
                {
                    p.AppendSpaces();
                    if (getterAccessorModifier != mainAccessorModifier)
                    {
                        p.AppendKeywordCSharp(AccessorModifierToString(getterAccessorModifier.Value));
                        p.AppendSpaces();
                    }
                    p.AppendKeywordCSharp("get;");
                }
                if (propertyInfo.CanWrite && setterAccessorModifier >= AccessorModifier.Protected)
                {
                    p.AppendSpaces();
                    if (setterAccessorModifier != mainAccessorModifier)
                    {
                        p.AppendKeywordCSharp(AccessorModifierToString(setterAccessorModifier.Value));
                        p.AppendSpaces();
                    }
                    p.AppendKeywordCSharp("set;");
                }
                p.AppendSpaces();
                p.AppendText("}");
                p.AppendCarriageReturn();
                return true;
            }
    
            static bool DealConstructor(ConstructorInfo constructorInfo, XWPFParagraph p, int spaceCount)
            {
                if (!(constructorInfo.IsPublic || constructorInfo.IsFamily))
                {
                    return false;
                }
    
                //if (constructorInfo.IsPrivate)
                //{
                //    return false;
                //}
    
                p.AppendSpaces(spaceCount);
                if (constructorInfo.IsPublic)
                {
                    p.AppendKeywordCSharp("public");
                }
                else if (constructorInfo.IsFamily)
                {
                    p.AppendKeywordCSharp("protected");
                }
                else if (constructorInfo.IsAssembly)
                {
                    p.AppendKeywordCSharp("internal");
                }
                else if (constructorInfo.IsFamilyOrAssembly)
                {
                    p.AppendKeywordCSharp("internal protected");
                }
                p.AppendSpaces();
    
    
                if (constructorInfo.IsAbstract)
                {
                    p.AppendKeywordCSharp("abstract");
                    p.AppendSpaces();
                }
    
                p.AppendClassCSharp(constructorInfo.DeclaringType.Name);
                p.AppendText("(");
                bool isFirst = true;
                foreach (var parameterInfo in constructorInfo.GetParameters())
                {
                    if (!isFirst)
                    {
                        p.AppendText(", ");
                    }
                    DispalyType(parameterInfo.ParameterType, p);
                    p.AppendSpaces();
                    p.AppendText(parameterInfo.Name);
                    isFirst = false;
                }
                p.AppendText(");");
                p.AppendCarriageReturn();
                return true;
            }
    
            static bool DealMethod(MethodInfo method, XWPFParagraph p, int spaceCount)
            {
                if (!(method.IsPublic || method.IsFamily))
                {
                    return false;
                }
                //if (method.IsPrivate)
                //{
                //    return false;
                //}
    
                if (method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))
                {
                    return false;
                }
                p.AppendSpaces(spaceCount);
                if (method.Name == "Finalize")
                {
                    p.AppendText("~");
                    p.AppendClassCSharp(method.DeclaringType.Name);
                    p.AppendText("();");
                    p.AppendCarriageReturn();
                    return true;
                }
    
                if (method.IsPublic)
                {
                    p.AppendKeywordCSharp("public");
                }
                else if (method.IsFamily)
                {
                    p.AppendKeywordCSharp("protected");
                }
                else if (method.IsAssembly)
                {
                    p.AppendKeywordCSharp("internal");
                }
                else if (method.IsFamilyAndAssembly)
                {
                    p.AppendKeywordCSharp("internal protected");
                }
                p.AppendSpaces();
    
                if (method.IsStatic)
                {
                    p.AppendKeywordCSharp("static");
                    p.AppendSpaces();
                }
                // a. override parent class method, 
                // b.implement a interface
                // both have Final & virtual keywords
                bool isSealed = false;
                if (method.IsFinal && method != method.GetBaseDefinition())
                {
                    p.AppendKeywordCSharp("sealed");
                    p.AppendSpaces();
                    isSealed = true;
                }
                if (method.IsVirtual)
                {
                    if (method != method.GetBaseDefinition())
                    {
                        p.AppendKeywordCSharp("override");
                    }
                    else
                    {
                        if (!method.IsFinal)
                        {
                            p.AppendKeywordCSharp("virtual");
                        }
                    }
                    p.AppendSpaces();
                }
                if (method.IsAbstract)
                {
                    p.AppendKeywordCSharp("abstract");
                    p.AppendSpaces();
                }
    
                DispalyType(method.ReturnType, p);
                p.AppendSpaces();
    
                p.AppendText(method.Name);
                p.AppendText("(");
    
    
                bool isFirst = true;
                foreach (var parameterInfo in method.GetParameters())
                {
                    if (!isFirst)
                    {
                        p.AppendText(", ");
                    }
    
                    if (parameterInfo.IsOut)
                    {
                        p.AppendKeywordCSharp("out");
                        p.AppendSpaces();
                    }
                    else if (parameterInfo.IsIn)
                    {
                        p.AppendKeywordCSharp("in");
                        p.AppendSpaces();
                    }
                    else if (parameterInfo.ParameterType.IsByRef)
                    {
                        p.AppendKeywordCSharp("ref");
                        p.AppendSpaces();
                    }
    
                    DispalyType(parameterInfo.ParameterType, p);
                    p.AppendSpaces();
                    p.AppendText(parameterInfo.Name);
                    if (IsShowParameterDefaultValue && parameterInfo.HasDefaultValue)
                    {
                        p.AppendSpaces();
                        p.AppendText("=");
                        p.AppendSpaces();
                        if (parameterInfo.DefaultValue == null)
                        {
                            p.AppendText("null");
                        }
                        else if (parameterInfo.ParameterType == typeof(string))
                        {
                            p.AppendText(""");
                            p.AppendText(parameterInfo.DefaultValue.ToString());
                            p.AppendText(""");
                        }
                        else if (parameterInfo.ParameterType == typeof(char))
                        {
                            p.AppendText("'");
                            p.AppendText(parameterInfo.DefaultValue.ToString());
                            p.AppendText("'");
                        }
                        else if (parameterInfo.ParameterType.IsEnum)
                        {
                            DispalyType(parameterInfo.ParameterType, p);
                            p.AppendText(".");
                            p.AppendText(parameterInfo.DefaultValue.ToString());
                        }
                        else
                        {
                            p.AppendText(parameterInfo.DefaultValue.ToString());
                        }
                    }
                    isFirst = false;
                }
    
                p.AppendText(");");
                p.AppendCarriageReturn();
                return true;
            }
    
            static void DispalyType(Type type, XWPFParagraph p)
            {
                // Nullable<> need change to like int?
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    DispalyType(type.GetGenericArguments()[0], p);
                    p.AppendText("?");
                    return;
                }
    
                var typeName = type.Name;
                if (typeName.Contains("`"))
                {
                    typeName = typeName.Substring(0, typeName.LastIndexOf('`'));
                }
                typeName = ChangeToNormalName(typeName);
                p.AppendClassCSharp(typeName);
                if (type.IsGenericType)
                {
                    p.AppendText("<");
                    bool isFisrt = true;
                    foreach (var genericArgumentType in type.GetGenericArguments())
                    {
                        if (!isFisrt)
                        {
                            p.AppendText(", ");
                        }
                        DispalyType(genericArgumentType, p);
                        isFisrt = false;
                    }
                    p.AppendText(">");
                }
            }
    
            static string ChangeToNormalName(string typeName)
            {
                typeName = typeName.TrimEnd('&');
                switch (typeName)
                {
                    case "Void": return "void";
                    case "Object": return "object";
                    case "String": return "string";
                    case "Boolean": return "bool";
                    case "Byte": return "byte";
                    case "Char": return "char";
                    case "Int16": return "short";
                    case "Int32": return "int";
                    case "Int64": return "long";
                    case "Single": return "float";
                    case "Double": return "double";
                    default:
                        return typeName;
                }
            }
    
            static XWPFParagraph DealEnum(Type type, XWPFDocument doc, int spaceCount)
            {
                if (type.IsNestedPrivate)
                {
                    return null;
                }
                var p = doc.CreateParagraph();
                if (type.GetCustomAttribute<FlagsAttribute>() != null)
                {
                    p.AppendSpaces(spaceCount);
                    p.AppendText("[");
                    p.AppendKeywordCSharp("Flags");
                    p.AppendText("]");
                    p.AppendCarriageReturn();
                }
                p.AppendSpaces(spaceCount);
                if (type.IsPublic)
                {
                    p.AppendKeywordCSharp("public");
                }
                else if (type.IsNestedAssembly)
                {
                    p.AppendKeywordCSharp("internal");
                }
                p.AppendSpaces();
    
                p.AppendKeywordCSharp("enum");
                p.AppendSpaces();
                p.AppendClassCSharp(type.Name);
    
                var tempSpaceCount = spaceCount;// - spaceIncreaseCountOfEachLevel > 0 ? spaceCount - spaceIncreaseCountOfEachLevel : 0;
                p.AppendCarriageReturn();
                p.AppendSpaces(tempSpaceCount);
                p.AppendText("{");
                p.AppendCarriageReturn();
    
                foreach (var enumName in type.GetEnumNames())
                {
                    p.AppendSpaces(spaceCount + spaceIncreaseCountOfEachLevel);
                    p.AppendText(enumName);
                    p.AppendText(",");
                    p.AppendCarriageReturn();
                }
                p.AppendSpaces(tempSpaceCount);
                p.AppendText("}");
                return p;
            }
    
            static XWPFParagraph DealStruct(Type type, XWPFDocument doc, int spaceCount)
            {
                if (!type.IsPublic)
                {
                    return null;
                }
                //if (type.IsNestedPrivate)
                //{
                //    return null;
                //}
                if (type.Name.StartsWith("<"))
                {
                    return null;
                }
                var p = doc.CreateParagraph();
                p.AppendSpaces(spaceCount);
                if (type.IsPublic)
                {
                    p.AppendKeywordCSharp("public");
                }
                else
                {
                    p.AppendKeywordCSharp("internal");
                }
                p.AppendSpaces();
    
    
                p.AppendKeywordCSharp("struct");
                p.AppendSpaces();
                p.AppendClassCSharp(type.Name);
    
                bool isFisrtInterface = true;
                foreach (var interfaceType in type.GetInterfaces())
                {
                    if (isFisrtInterface)
                    {
                        p.AppendText(" : ");
                    }
                    else
                    {
                        p.AppendText(", ");
                    }
                    DispalyType(interfaceType, p);
                    isFisrtInterface = false;
                }
                p.AppendCarriageReturn();
    
                var tempSpaceCount = spaceCount;// - spaceIncreaseCountOfEachLevel > 0 ? spaceCount - spaceIncreaseCountOfEachLevel : 0;
                p.AppendSpaces(tempSpaceCount);
                p.AppendText("{");
                p.AppendCarriageReturn();
    
    
    
                bool hasAddedSomething = false;
                foreach (var filedInfo in type.GetFields(bindingFlags))
                {
                    if (!filedInfo.IsPublic && !filedInfo.IsFamily)
                    {
                        continue;
                    }
                    DealFieldInfo(filedInfo, p, spaceCount + spaceIncreaseCountOfEachLevel);
                    hasAddedSomething = true;
                }
                if (hasAddedSomething) p.AppendCarriageReturn();
    
    
    
    
                hasAddedSomething = false;
                foreach (ConstructorInfo constructorInfo in type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
                {
                    if (DealConstructor(constructorInfo, p, spaceCount + spaceIncreaseCountOfEachLevel) == true)
                    {
                        hasAddedSomething = true;
                    }
                }
                if (hasAddedSomething) p.AppendCarriageReturn();
    
    
    
                hasAddedSomething = false;
                foreach (var propertyInfo in type.GetProperties(bindingFlags))
                {
                    if (DealProperty(propertyInfo, p, spaceCount + spaceIncreaseCountOfEachLevel) == true)
                    {
                        hasAddedSomething = true;
                    }
                }
                if (hasAddedSomething) p.AppendCarriageReturn();
    
    
    
                hasAddedSomething = false;
                foreach (MethodInfo method in type.GetMethods(bindingFlags))
                {
                    if (DealMethod(method, p, spaceCount + spaceIncreaseCountOfEachLevel) == true)
                    {
                        hasAddedSomething = true;
                    }
                }
                if (hasAddedSomething) p.AppendCarriageReturn();
                p.RemoveRun(p.Runs.Count - 1);
                p.AppendSpaces(tempSpaceCount);
                p.AppendText("}");
                return p;
            }
    
            static AccessorModifier GetAccessorModifier(MethodInfo method)
            {
                if (method.IsPublic)
                {
                    return AccessorModifier.Public;
                }
                if (method.IsAssembly)
                {
                    return AccessorModifier.Internal;
                }
                if (method.IsFamily)
                {
                    return AccessorModifier.Protected;
                }
                if (method.IsFamilyOrAssembly)
                {
                    return AccessorModifier.InternalProtected;
                }
    
                return AccessorModifier.Private;
            }
    
            static AccessorModifier GetHighAccessorModifier(AccessorModifier? a, AccessorModifier? b)
            {
                // a or b at least have one value
                if (a.HasValue && b.HasValue)
                {
                    return (AccessorModifier)Math.Max((int)a.Value, (int)b.Value);
                }
                else if (a.HasValue == false)
                {
                    return b.Value;
                }
                else
                {
                    return a.Value;
                }
            }
    
            static string AccessorModifierToString(AccessorModifier accessorModifier)
            {
                switch (accessorModifier)
                {
                    case AccessorModifier.Public:
                        return "public";
                    case AccessorModifier.Internal:
                        return "internal";
                    case AccessorModifier.Protected:
                        return "protected";
                        break;
                    case AccessorModifier.InternalProtected:
                        return "internal protected";
                    case AccessorModifier.Private:
                        return "private";
                    default:
                        return "";
                }
            }
    
            private enum AccessorModifier
            {
                Public = 100,
                Protected = 95,
                Internal = 90,
                InternalProtected = 80,
                Private = 70,
            }
        }
    
        internal static class NopiExtension
        {
            internal static XWPFRun AppendText(this XWPFParagraph paragraph, string text, string color = "000000")
            {
                XWPFRun run = paragraph.CreateRun();
                run.SetText(text);
                run.SetColor(color);
                return run;
            }
    
            internal static XWPFRun AppendSpaces(this XWPFParagraph paragraph, int spaceCount = 1)
            {
                return paragraph.AppendText(new string(' ', spaceCount));
            }
    
            internal static XWPFRun AppendKeywordCSharp(this XWPFParagraph paragraph, string text)
            {
                return paragraph.AppendText(text, InterfaceExportHelper.CSharpKeywordColor);
            }
    
            internal static XWPFRun AppendClassCSharp(this XWPFParagraph paragraph, string text)
            {
                return paragraph.AppendText(text, InterfaceExportHelper.CSharpClassColor);
            }
    
            internal static XWPFRun AppendCarriageReturn(this XWPFParagraph paragraph)
            {
                var run = paragraph.CreateRun();
                run.AddCarriageReturn();
                return run;
            }
        }

          用法

    var assemblyPath = @"D:ClientinDebugClient.dll";
    var outputDocPath = @"D:Client.docx";
    
    InterfaceExportHelper.IsShowParameterDefaultValue = false;
    InterfaceExportHelper.SeparateInterfaceToDocument(assemblyPath, outputDocPath);

          

  • 相关阅读:
    scrapy xpath 定位节点获取数据
    pandas 获取增量数据
    10秒解决80端口被占用
    VS code 自定义快捷键
    解决npm 的 shasum check failed for错误
    JSON.parse与eval的区别
    display:flex,用这个布局就像开挂了!!!
    几款前端IDE工具:Sublime、Atom、VSCode比较
    npm install -S -D -g 有什么区别
    Vue框架学习——使用nvm下载8.12.0以后版本没有npm文件的解决办法
  • 原文地址:https://www.cnblogs.com/zhouandke/p/10135438.html
Copyright © 2011-2022 走看看