PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/TechEdWebApiDemo/Areas/HelpPage/XmlDocumentationProvider.cs

https://github.com/garchibald/TechEdWebApiDemo
C# | 112 lines | 90 code | 13 blank | 9 comment | 17 complexity | de53d5fa3e889f7083e2f7cf5319aa5d MD5 | raw file
  1. using System;
  2. using System.Linq;
  3. using System.Reflection;
  4. using System.Web.Http.Controllers;
  5. using System.Web.Http.Description;
  6. using System.Xml.XPath;
  7. using System.Globalization;
  8. namespace TechEdWebApiDemo.Areas.HelpPage
  9. {
  10. /// <summary>
  11. /// A custom <see cref="IDocumentationProvider"/> that reads the API documentation from an XML documentation file.
  12. /// </summary>
  13. public class XmlDocumentationProvider : IDocumentationProvider
  14. {
  15. private XPathNavigator _documentNavigator;
  16. private const string _methodExpression = "/doc/members/member[@name='M:{0}']";
  17. private const string _parameterExpression = "param[@name='{0}']";
  18. /// <summary>
  19. /// Initializes a new instance of the <see cref="XmlDocumentationProvider"/> class.
  20. /// </summary>
  21. /// <param name="documentPath">The physical path to XML document.</param>
  22. public XmlDocumentationProvider(string documentPath)
  23. {
  24. if (documentPath == null)
  25. {
  26. throw new ArgumentNullException("documentPath");
  27. }
  28. XPathDocument xpath = new XPathDocument(documentPath);
  29. _documentNavigator = xpath.CreateNavigator();
  30. }
  31. public virtual string GetDocumentation(HttpActionDescriptor actionDescriptor)
  32. {
  33. XPathNavigator methodNode = GetMethodNode(actionDescriptor);
  34. if (methodNode != null)
  35. {
  36. XPathNavigator summaryNode = methodNode.SelectSingleNode("summary");
  37. if (summaryNode != null)
  38. {
  39. return summaryNode.Value.Trim();
  40. }
  41. }
  42. return null;
  43. }
  44. public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
  45. {
  46. ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
  47. if (reflectedParameterDescriptor != null)
  48. {
  49. XPathNavigator methodNode = GetMethodNode(reflectedParameterDescriptor.ActionDescriptor);
  50. if (methodNode != null)
  51. {
  52. string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
  53. XPathNavigator parameterNode = methodNode.SelectSingleNode(String.Format(CultureInfo.InvariantCulture, _parameterExpression, parameterName));
  54. if (parameterNode != null)
  55. {
  56. return parameterNode.Value.Trim();
  57. }
  58. }
  59. }
  60. return null;
  61. }
  62. private XPathNavigator GetMethodNode(HttpActionDescriptor actionDescriptor)
  63. {
  64. ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
  65. if (reflectedActionDescriptor != null)
  66. {
  67. string selectExpression = String.Format(CultureInfo.InvariantCulture, _methodExpression, GetMemberName(reflectedActionDescriptor.MethodInfo));
  68. return _documentNavigator.SelectSingleNode(selectExpression);
  69. }
  70. return null;
  71. }
  72. private static string GetMemberName(MethodInfo method)
  73. {
  74. string name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", method.DeclaringType.FullName, method.Name);
  75. ParameterInfo[] parameters = method.GetParameters();
  76. if (parameters.Length != 0)
  77. {
  78. string[] parameterTypeNames = parameters.Select(param => GetTypeName(param.ParameterType)).ToArray();
  79. name += String.Format(CultureInfo.InvariantCulture, "({0})", String.Join(",", parameterTypeNames));
  80. }
  81. return name;
  82. }
  83. private static string GetTypeName(Type type)
  84. {
  85. if (type.IsGenericType)
  86. {
  87. // Format the generic type name to something like: Generic{System.Int32,System.String}
  88. Type genericType = type.GetGenericTypeDefinition();
  89. Type[] genericArguments = type.GetGenericArguments();
  90. string typeName = genericType.FullName;
  91. // Trim the generic parameter counts from the name
  92. typeName = typeName.Substring(0, typeName.IndexOf('`'));
  93. string[] argumentTypeNames = genericArguments.Select(t => GetTypeName(t)).ToArray();
  94. return String.Format(CultureInfo.InvariantCulture, "{0}{{{1}}}", typeName, String.Join(",", argumentTypeNames));
  95. }
  96. return type.FullName;
  97. }
  98. }
  99. }