欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

asp.netmvc抽取控制器备注说明

程序员文章站 2024-02-27 18:17:39
...

主要是读取xml描述和通过反射获取dll中的type,思想参考swagger,但是因为swagger没有mvc包,只能自己写一个了

1、首先需要把项目属性→生成→输出→xml文档文件 勾选上,勾选上之后你的bin目录下就会有一个xml文件,保存的是当前项目的所有类和方法属性备注
asp.netmvc抽取控制器备注说明
如果有一些用到的model类在别的项目里,那那个项目也需要勾选上

2、由于有时需要返回的model的说明,所以我写了一个特性什么都不做,只用来标记需要描述的返回的类,方便反射读取方法的自定义特性,
asp.netmvc抽取控制器备注说明

  public class ResponseTypeAttribute : Attribute
    {
        public ResponseTypeAttribute(Type t)
        {
        }
    }

3、首先定义一些需要用到的类

/// <summary>
/// 接口描述类
/// </summary>
public class InterfaceSpecificationDesc
{
    public string ActionSummary { get; set; }
    public string ControllerName { get; set; }
    public string ActionName { get; set; }
    public string HttpType { get; set; }
    public List<ParamSpecification> Params { get; set; }
    public string ResponseDesc { get; set; }
    public List<ParamSpecification> ResponseModel { get; set; }
}

/// <summary>
/// 参数描述类
/// </summary>
public class ParamSpecification
{
    public string Name { get; set; }
    public string @Type { get; set; }
    public string Desc { get; set; }
    public string DefaultValue { get; set; }
    public List<ParamSpecification> @params { get; set; }
}

/// <summary>
/// xml读记录的属性方法的描述
/// </summary>
public class XmlInfo
{
    public string member { get; set; }
    public string summary { get; set; }
    public string returns { get; set; }
    public List<XmlParam> @params { get; set; }
}

/// <summary>
/// xml中记录的方法参数
/// </summary>
public class XmlParam
{
    public string name { get; set; }
    public string desc { get; set; }
}

4、获取描述的主要代码

			var xmls = getXmlFile(xml);//读取xml到内存中,转换成List<XmlInfo>格式

            var a = Assembly.LoadFile(path);//读取一个dll
            Type[] types = a.GetTypes();//获取曾程序集中定义的类型

            var descs = new List<InterfaceSpecificationDesc>();//最终结果
            var rg = new Regex("^[A-Za-z]+$");
            foreach (var controller in types)
            {
                if (!rg.IsMatch(controller.Name) || !controller.Name.EndsWith("Controller"))//过滤掉不是控制器的类型,正则太难了QAQ
                {
                    continue;
                }

                foreach (var action in controller.GetMethods())//获取当前控制器的所有方法
                {
                    if (action.Name.StartsWith("get_") || action.Name.StartsWith("set_") || new string[] { "Dispose", "Equals", "GetHashCode", "GetType", "ToString" }.Contains(action.Name))//过滤到不是我们需要的方法和
                    {
                        continue;
                    }

                    var @params = new List<ParamSpecification>();//当前方法的参数
                    var paramsdesc = xmls.FirstOrDefault(p => p.member.Contains(controller.Name + "." + action.Name))?.@params;
                    foreach (var param in action.GetParameters())
                    {
                        var paramModel = new List<ParamSpecification>();
                        var rmpType = param.ParameterType;
                        if (!names.Contains(rmpType.Name))
                        {
                            paramModel = getParamSpecification(rmpType, xmls);//自定义类型,从xml中读取备注
                        }
                        @params.Add(new ParamSpecification
                        {
                            Name = param.Name,
                            Type = param.ParameterType.Name == "List`1" ? param.ParameterType.GenericTypeArguments[0].Name + "[]" : param.ParameterType.Name,
                            DefaultValue = param.DefaultValue + "",
                            Desc = paramsdesc?.FirstOrDefault(p => p.name == param.Name)?.desc,
                            @params = paramModel
                        });
                    }

                    var tmp = action.Attributes;
                    string httptype = "", respons = "";
                    var responseModel = new List<ParamSpecification>();
                    foreach (var attribute in action.CustomAttributes)//自定义特性
                    {
                        if (attribute.AttributeType.Name.Contains("ost"))
                        {
                            httptype = "Post";
                        }
                        else if (attribute.AttributeType.Name.Contains("et"))
                        {
                            httptype = "Get";
                        }

                        if (attribute.AttributeType.Name.Contains("ResponseType"))//专门标注的返回类型
                        {
                            var value = attribute.ConstructorArguments.FirstOrDefault().Value as Type;
                            respons = value.FullName;
                            responseModel = getParamSpecification(value, xmls);//自定义类型,从xml中读取备注
                        }
                    }

                    descs.Add(new InterfaceSpecificationDesc
                    {
                        ControllerName = controller.Name.Replace("Controller", ""),
                        ActionName = action.Name,
                        ActionSummary = xmls.FirstOrDefault(p => p.member.Contains(controller.Name + "." + action.Name))?.summary,
                        HttpType = string.IsNullOrWhiteSpace(httptype) ? "Post/Get" : httptype,
                        Params = @params,
                        ResponseDesc = respons,
                        ResponseModel = responseModel
                    });
                }
            }
            //JsonConvert
            descs = descs.OrderBy(p => p.ControllerName).ToList();
            

用到的一些方法

    	/// <summary>
        /// 从xml中拿到目标type的备注
        /// </summary>
        /// <param name="value"></param>
        /// <param name="xmls"></param>
        /// <returns></returns>
        private static List<ParamSpecification> getParamSpecification(Type value, List<XmlInfo> xmls)
        {
            var ret = new List<ParamSpecification>();
            while (value.Name != "Object")
            {
                if (value.Name == "List`1")
                {
                    value = value.GenericTypeArguments[0];
                }
                if (names.Contains(value.Name))
                {
                    return ret;
                }
                if (value.Name.Contains("[]"))
                {
                    value = value.Assembly.GetType(value.FullName.Replace("[]", ""));
                }

                foreach (var property in value.GetProperties())
                {
                    ret.Add(new ParamSpecification
                    {
                        Name = property.Name,
                        Type = property.PropertyType.Name,
                        Desc = xmls.FirstOrDefault(p => p.member.Contains(value.FullName + "." + property.Name))?.summary
                    });
                }
                value = value.BaseType;
            }
            return ret;
        }
        
 		private static string getName(string str)
        {
            var ret = rgName.Match(str).Value;
            ret = ret.Replace("name=", "");
            if (ret.Length > 0)
            {
                ret = ret.TrimEnd('"');
                ret = ret.TrimStart('"');
            }

            return ret;
        }
        private static string getValue(string str)
        {
            var ret = rgValue.Match(str).Value;
            ret = ret.TrimStart('>');
            ret = ret.TrimEnd('<');
            return ret;
        }

5、前端页面简单写做一下
6、最终效果:
需要分析的dll中,控制器是这么写的:
asp.netmvc抽取控制器备注说明
返回model和参数model:
asp.netmvc抽取控制器备注说明
最终效果:
asp.netmvc抽取控制器备注说明
asp.netmvc抽取控制器备注说明