以编程方式在运行时获取评论摘要(Programmatically get Summary comme

2019-07-23 02:18发布

我正在寻找一种方法以编程方式获得的ASP.net方法的XML的意见摘要部分。

我看过以前的相关的职位,他们不提供在网络环境中这样做的一种方式。

我不能使用任何第三方应用程序,并且由于网络环境Visual Studio插件的是没有多大用处无论是。

我已经找到了工作的解决方案最接近的事是JimBlackler项目,但它只能在DLL的。

当然,类似的供应.CS文件,得到XML文档“将是最佳的。


现在的情况

我有一个Web服务,并试图动态生成的文档了。

阅读方法和属性很容易,但让每个方法的总结是扔我赶走了一下。

/// <summary>
/// This Is what I'm trying to read
/// </summary>
public class Some_Method(){}

Answer 1:

该XML概述并不存储在.NET程序集 - 这是可选写入到一个XML文件作为构建的一部分(假设你使用Visual Studio)。

因此没有办法通过在编译的.NET程序集(无论是.exe或.dll)反射来“拉出来”每种方法的XML摘要 - 因为数据根本不存在为你拉出来。 如果你想要的数据,你就必须构建环境指示输出XML文件作为构建过程的一部分,并解析这些XML文件在运行时获得的摘要信息。



Answer 2:

A Workaround - Using reflection on Program.DLL/EXE together with Program.XML file

If you take a look at the sibling .XML file generated by Visual Studio you will see that there is a fairly flat hierarchy of /members/member. All you have to do is get hold on each method from your DLL via MethodInfo object. Once you have this object you turn to the XML and use XPATH to get the member containing the XML documentation for this method.

Members are preceded by a letter. XML doc for methods are preceded by "M:" for class by "T:" etc.

Load your sibling XML

string docuPath = dllPath.Substring(0, dllPath.LastIndexOf(".")) + ".XML";

if (File.Exists(docuPath))
{
  _docuDoc = new XmlDocument();
  _docuDoc.Load(docuPath);
}

Use this xpath to get the member representing the method XML docu

string path = "M:" + mi.DeclaringType.FullName + "." + mi.Name;

XmlNode xmlDocuOfMethod = _docuDoc.SelectSingleNode(
    "//member[starts-with(@name, '" + path + "')]");

Now scan childnodes for all the rows of "///" Sometimes the /// Summary contains extra blanks, if this bothers use this to remove

var cleanStr = Regex.Replace(row.InnerXml, @"\s+", " ");


Answer 3:

你可以“文件”用你的方法System.ComponentModel.DataAnnotations.DisplayAttribute属性,如

[Display(Name = "Foo", Description = "Blah")]
void Foo()
{
}

然后用反射拉描述在运行时。



Answer 4:

被删除的帖子,由@OleksandrIeremenko做,在这个线程链接到这篇文章https://jimblackler.net/blog/?p=49这是我的解决方案的基础。

下面是吉姆Blackler的代码进行扩展方法关闭的MemberInfo和类型的对象,并补充说,返回的摘要文本或空字符串,如果没有可用的代码的修改。

用法

var typeSummary = typeof([Type Name]).GetSummary();
var methodSummary = typeof([Type Name]).GetMethod("[Method Name]").GetSummary();

扩展类

/// <summary>
/// Utility class to provide documentation for various types where available with the assembly
/// </summary>
public static class DocumenationExtensions
{
    /// <summary>
    /// Provides the documentation comments for a specific method
    /// </summary>
    /// <param name="methodInfo">The MethodInfo (reflection data ) of the member to find documentation for</param>
    /// <returns>The XML fragment describing the method</returns>
    public static XmlElement GetDocumentation(this MethodInfo methodInfo)
    {
        // Calculate the parameter string as this is in the member name in the XML
        var parametersString = "";
        foreach (var parameterInfo in methodInfo.GetParameters())
        {
            if (parametersString.Length > 0)
            {
                parametersString += ",";
            }

            parametersString += parameterInfo.ParameterType.FullName;
        }

        //AL: 15.04.2008 ==> BUG-FIX remove “()” if parametersString is empty
        if (parametersString.Length > 0)
            return XmlFromName(methodInfo.DeclaringType, 'M', methodInfo.Name + "(" + parametersString + ")");
        else
            return XmlFromName(methodInfo.DeclaringType, 'M', methodInfo.Name);
    }

    /// <summary>
    /// Provides the documentation comments for a specific member
    /// </summary>
    /// <param name="memberInfo">The MemberInfo (reflection data) or the member to find documentation for</param>
    /// <returns>The XML fragment describing the member</returns>
    public static XmlElement GetDocumentation(this MemberInfo memberInfo)
    {
        // First character [0] of member type is prefix character in the name in the XML
        return XmlFromName(memberInfo.DeclaringType, memberInfo.MemberType.ToString()[0], memberInfo.Name);
    }
    /// <summary>
    /// Returns the Xml documenation summary comment for this member
    /// </summary>
    /// <param name="memberInfo"></param>
    /// <returns></returns>
    public static string GetSummary(this MemberInfo memberInfo)
    {
        var element = memberInfo.GetDocumentation();
        var summaryElm = element?.SelectSingleNode("summary");
        if (summaryElm == null) return "";
        return summaryElm.InnerText.Trim();
    }

    /// <summary>
    /// Provides the documentation comments for a specific type
    /// </summary>
    /// <param name="type">Type to find the documentation for</param>
    /// <returns>The XML fragment that describes the type</returns>
    public static XmlElement GetDocumentation(this Type type)
    {
        // Prefix in type names is T
        return XmlFromName(type, 'T', "");
    }

    /// <summary>
    /// Gets the summary portion of a type's documenation or returns an empty string if not available
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static string GetSummary(this Type type)
    {
        var element = type.GetDocumentation();
        var summaryElm = element?.SelectSingleNode("summary");
        if (summaryElm == null) return "";
        return summaryElm.InnerText.Trim();
    }

    /// <summary>
    /// Obtains the XML Element that describes a reflection element by searching the 
    /// members for a member that has a name that describes the element.
    /// </summary>
    /// <param name="type">The type or parent type, used to fetch the assembly</param>
    /// <param name="prefix">The prefix as seen in the name attribute in the documentation XML</param>
    /// <param name="name">Where relevant, the full name qualifier for the element</param>
    /// <returns>The member that has a name that describes the specified reflection element</returns>
    private static XmlElement XmlFromName(this Type type, char prefix, string name)
    {
        string fullName;

        if (string.IsNullOrEmpty(name))
            fullName = prefix + ":" + type.FullName;
        else
            fullName = prefix + ":" + type.FullName + "." + name;

        var xmlDocument = XmlFromAssembly(type.Assembly);

        var matchedElement = xmlDocument["doc"]["members"].SelectSingleNode("member[@name='" + fullName + "']") as XmlElement;

        return matchedElement;
    }

    /// <summary>
    /// A cache used to remember Xml documentation for assemblies
    /// </summary>
    private static readonly Dictionary<Assembly, XmlDocument> Cache = new Dictionary<Assembly, XmlDocument>();

    /// <summary>
    /// A cache used to store failure exceptions for assembly lookups
    /// </summary>
    private static readonly Dictionary<Assembly, Exception> FailCache = new Dictionary<Assembly, Exception>();

    /// <summary>
    /// Obtains the documentation file for the specified assembly
    /// </summary>
    /// <param name="assembly">The assembly to find the XML document for</param>
    /// <returns>The XML document</returns>
    /// <remarks>This version uses a cache to preserve the assemblies, so that 
    /// the XML file is not loaded and parsed on every single lookup</remarks>
    public static XmlDocument XmlFromAssembly(this Assembly assembly)
    {
        if (FailCache.ContainsKey(assembly))
        {
            throw FailCache[assembly];
        }

        try
        {

            if (!Cache.ContainsKey(assembly))
            {
                // load the docuemnt into the cache
                Cache[assembly] = XmlFromAssemblyNonCached(assembly);
            }

            return Cache[assembly];
        }
        catch (Exception exception)
        {
            FailCache[assembly] = exception;
            throw exception;
        }
    }

    /// <summary>
    /// Loads and parses the documentation file for the specified assembly
    /// </summary>
    /// <param name="assembly">The assembly to find the XML document for</param>
    /// <returns>The XML document</returns>
    private static XmlDocument XmlFromAssemblyNonCached(Assembly assembly)
    {
        var assemblyFilename = assembly.CodeBase;

        const string prefix = "file:///";

        if (assemblyFilename.StartsWith(prefix))
        {
            StreamReader streamReader;

            try
            {
                streamReader = new StreamReader(Path.ChangeExtension(assemblyFilename.Substring(prefix.Length), ".xml"));
            }
            catch (FileNotFoundException exception)
            {
                throw new Exception("XML documentation not present (make sure it is turned on in project properties when building)", exception);
            }

            var xmlDocument = new XmlDocument();
            xmlDocument.Load(streamReader);
            return xmlDocument;
        }
        else
        {
            throw new Exception("Could not ascertain assembly filename", null);
        }
    }
}


Answer 5:

你可以看一下https://github.com/NSwag/NSwag -源的NuGet NSwag.CodeGeneration -它变得总结为好,使用

var generator = new WebApiAssemblyToSwaggerGenerator(settings);<br/>
var swaggerService = generator.GenerateForController("namespace.someController");<br/>
// string with comments <br/>
var swaggerJson = swaggerService.ToJson(); 

(尝试ILSPY反编译器对你的DLL,你检查代码和注释)



Answer 6:

如果你有机会获得源代码,你正在试图获得征求意见,那么你可以使用罗斯林编译器平台来做到这一点。 基本上,它使您可以访问所有的中介编译器的元数据,你可以做你想做任何事的。

这是一个有点比其他人所提出的建议比较复杂,但根据您的需求是什么,可能是一种选择。

它看起来像这个帖子有类似的东西,一个代码示例。



文章来源: Programmatically get Summary comments at runtime