当前位置: 移动技术网 > IT编程>开发语言>.net > 利用反射生成接口列表

利用反射生成接口列表

2018年12月18日  | 移动技术网IT编程  | 我要评论

2017年第2号台风,poser6,国家信访局网

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

      之前用的是微软的一个免费工具, 但好久都没有更新了, 对新一点的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:\client\bin\debug\client.dll";
var outputdocpath = @"d:\client.docx";

interfaceexporthelper.isshowparameterdefaultvalue = false;
interfaceexporthelper.separateinterfacetodocument(assemblypath, outputdocpath);

 

 

 

      

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网