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

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

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

2、由于有时需要返回的model的说明,所以我写了一个特性什么都不做,只用来标记需要描述的返回的类,方便反射读取方法的自定义特性,
在这里插入图片描述

  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中,控制器是这么写的:
在这里插入图片描述
返回model和参数model:
在这里插入图片描述
最终效果:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值