Web API 实体显示注释

我看园子里关于Web API的注释都是关于方法的,并没有显示实体注释的方法,今天花了一些时间搞了一下

其实注释的显示就是根据类库的XML文档文件生成的。

首先你要将所用到的类库生成XML文档文件:

在HelpPageConfig这个类中修改如下,添加多个用到的类库XML文件,原来只能添加一个

MultipleXmlDocumentationProvider代码,和XmlDocumentationProvider基本类似

复制代码
/// <summary>
/// 多个XML注释
/// </summary>
public class MultipleXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
{
    private IList<XPathNavigator> _documentNavigators;
    private const string TypeExpression = "/doc/members/member[@name='T:{0}']";
    private const string MethodExpression = "/doc/members/member[@name='M:{0}']";
    private const string PropertyExpression = "/doc/members/member[@name='P:{0}']";
    private const string FieldExpression = "/doc/members/member[@name='F:{0}']";
    private const string ParameterExpression = "param[@name='{0}']";

    /// <summary>
    /// Initializes a new instance of the <see cref="XmlDocumentationProvider"/> class.
    /// </summary>
    /// <param name="documentPaths">List of physical paths to XML documents.</param>
    public MultipleXmlDocumentationProvider(params string[] documentPaths)
    {
        if (!documentPaths.Any())
        {
            throw new ArgumentNullException("documentPaths");
        }

        //读取全部XML文档
        var documents = documentPaths.Where(p => File.Exists(p)).ToList();

        _documentNavigators = documents.Select(p => new XPathDocument(p).CreateNavigator()).ToList();
    }

    public string GetDocumentation(HttpControllerDescriptor controllerDescriptor)
    {
        XPathNavigator typeNode = GetTypeNode(controllerDescriptor.ControllerType);
        return GetTagValue(typeNode, "summary");
    }

    public virtual string GetDocumentation(HttpActionDescriptor actionDescriptor)
    {
        XPathNavigator methodNode = GetMethodNode(actionDescriptor);
        return GetTagValue(methodNode, "summary");
    }

    public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
    {
        ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
        if (reflectedParameterDescriptor != null)
        {
            XPathNavigator methodNode = GetMethodNode(reflectedParameterDescriptor.ActionDescriptor);
            if (methodNode != null)
            {
                string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
                XPathNavigator parameterNode = methodNode.SelectSingleNode(String.Format(CultureInfo.InvariantCulture, ParameterExpression, parameterName));
                if (parameterNode != null)
                {
                    return parameterNode.Value.Trim();
                }
            }
        }

        return null;
    }

    public string GetResponseDocumentation(HttpActionDescriptor actionDescriptor)
    {
        XPathNavigator methodNode = GetMethodNode(actionDescriptor);
        return GetTagValue(methodNode, "returns");
    }

    public string GetDocumentation(MemberInfo member)
    {
        string memberName = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", GetTypeName(member.DeclaringType), member.Name);
        string expression = member.MemberType == MemberTypes.Field ? FieldExpression : PropertyExpression;
        string selectExpression = String.Format(CultureInfo.InvariantCulture, expression, memberName);

        var propertyNode = _documentNavigators.Select(n => n.SelectSingleNode(selectExpression)).FirstOrDefault(n => n != null);

        return GetTagValue(propertyNode, "summary");
    }

    public string GetDocumentation(Type type)
    {
        XPathNavigator typeNode = GetTypeNode(type);
        return GetTagValue(typeNode, "summary");
    }

    private XPathNavigator GetMethodNode(HttpActionDescriptor actionDescriptor)
    {
        ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
        if (reflectedActionDescriptor != null)
        {
            string selectExpression = String.Format(CultureInfo.InvariantCulture, MethodExpression, GetMemberName(reflectedActionDescriptor.MethodInfo));
            return _documentNavigators.Select(n => n.SelectSingleNode(selectExpression)).FirstOrDefault(n => n != null);
        }

        return null;
    }

    private static string GetMemberName(MethodInfo method)
    {
        string name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", GetTypeName(method.DeclaringType), method.Name);
        ParameterInfo[] parameters = method.GetParameters();
        if (parameters.Length != 0)
        {
            string[] parameterTypeNames = parameters.Select(param => GetTypeName(param.ParameterType)).ToArray();
            name += String.Format(CultureInfo.InvariantCulture, "({0})", String.Join(",", parameterTypeNames));
        }

        return name;
    }

    private static string GetTagValue(XPathNavigator parentNode, string tagName)
    {
        if (parentNode != null)
        {
            XPathNavigator node = parentNode.SelectSingleNode(tagName);
            if (node != null)
            {
                return node.Value.Trim();
            }
        }

        return null;
    }

    private XPathNavigator GetTypeNode(Type type)
    {
        string controllerTypeName = GetTypeName(type);
        string selectExpression = String.Format(CultureInfo.InvariantCulture, TypeExpression, controllerTypeName);
        return _documentNavigators.Select(n => n.SelectSingleNode(selectExpression)).FirstOrDefault(n => n != null);
    }

    private static string GetTypeName(Type type)
    {
        string name = type.FullName;
        if (type.IsGenericType)
        {
            // Format the generic type name to something like: Generic{System.Int32,System.String}
            Type genericType = type.GetGenericTypeDefinition();
            Type[] genericArguments = type.GetGenericArguments();
            string genericTypeName = genericType.FullName;

            // Trim the generic parameter counts from the name
            genericTypeName = genericTypeName.Substring(0, genericTypeName.IndexOf('`'));
            string[] argumentTypeNames = genericArguments.Select(t => GetTypeName(t)).ToArray();
            name = String.Format(CultureInfo.InvariantCulture, "{0}{{{1}}}", genericTypeName, String.Join(",", argumentTypeNames));
        }
        if (type.IsNested)
        {
            // Changing the nested type name from OuterType+InnerType to OuterType.InnerType to match the XML documentation syntax.
            name = name.Replace("+", ".");
        }

        return name;
    }
}
复制代码

 

成功显示图:

 参考链接:

http://stackoverflow.com/questions/21393754/helppage-xml-documentation-when-controllers-or-models-in-different-assembly

 

posted on   Jade_K  阅读(1839)  评论(1编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示