{"id":49,"date":"2008-03-23T16:00:24","date_gmt":"2008-03-23T15:00:24","guid":{"rendered":"http:\/\/jimblackler.com\/blog\/?p=49"},"modified":"2008-04-18T21:30:14","modified_gmt":"2008-04-18T20:30:14","slug":"obtaining-inline-xml-c-documentation-at-runtime-using-net-20","status":"publish","type":"post","link":"https:\/\/jimblackler.com\/?p=49","title":{"rendered":"Obtaining inline XML C# documentation at runtime using .NET 2.0"},"content":{"rendered":"<p>C# .NET provides a standard mechanism for programmers to inline XML documentation in their programs. Classes, functions, properties and more can be augmented with comments, and the build system creates amalgamated XML files accompanying the program output. A variety of tools such as Sandcastle can build help files from the data. Visual Studio 2005 and 2008 also supports the scheme with keyboard shortcuts and optional build warnings for missing comments.<\/p>\n<div id=\"ig-sh-1\" class=\"syntax_hilite\">\n\n\t\n\t<div class=\"code\">\n\t\t<ol class=\"csharp\" style=\"font-family:monospace\"><li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #008080;font-style: italic\">\/\/\/ &lt;summary&gt;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #008080;font-style: italic\">\/\/\/ An example C# class<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #008080;font-style: italic\">\/\/\/ &lt;\/summary&gt;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #008080;font-style: italic\">\/\/\/ &lt;remarks&gt;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #008080;font-style: italic\">\/\/\/ This class illustrates how a class can be marked up with inline C# comments<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #008080;font-style: italic\">\/\/\/ &lt;\/remarks&gt;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #6666cc;font-weight: bold\">class<\/span> SomeExampleClass<\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #008000\">&#123;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp; &nbsp; <span style=\"color: #008080;font-style: italic\">\/\/\/ &lt;summary&gt;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp; &nbsp; <span style=\"color: #008080;font-style: italic\">\/\/\/ An example of a property<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp; &nbsp; <span style=\"color: #008080;font-style: italic\">\/\/\/ &lt;\/summary&gt;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp; &nbsp; <span style=\"color: #0600FF;font-weight: bold\">public<\/span> <span style=\"color: #6666cc;font-weight: bold\">int<\/span> ExampleProperty<\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp; &nbsp; <span style=\"color: #008000\">&#123;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp; &nbsp; &nbsp; &nbsp; <span style=\"color: #0600FF;font-weight: bold\">get<\/span> <span style=\"color: #008000\">&#123;<\/span> <span style=\"color: #0600FF;font-weight: bold\">return<\/span> somePrivateVar<span style=\"color: #008000\">;<\/span> <span style=\"color: #008000\">&#125;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">&nbsp; &nbsp; <span style=\"color: #008000\">&#125;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\"><span style=\"color: #008000\">&#125;<\/span><\/div><\/li>\n<\/ol>\t<\/div>\n\n<\/div>\n\n<p>Unfortunately, many programmers have observed that there\u2019s no way to discover these comments at runtime by reflection. All manner of alternative information can be accessed with reflection \u2013 but not the XML comments.<\/p>\n<h2>The solution<\/h2>\n<p>This documentation <i>can<\/i> be discovered at run time with a little extra code, as I will demonstrate. The reason the comments can\u2019t be discovered by reflection alone is because they are not included in the .NET assemblies (.EXE or .DLL files), but are conventionally included as .XML files to accompany the assembly files.<\/p>\n<p>I\u2019ve provided a simply class library for .NET 2.0 called DocsByReflection that will when possible return an XmlElement that describes a given type or member. This can be used to easily extract comments at runtime. Here\u2019s an example of how:<\/p>\n<div id=\"ig-sh-2\" class=\"syntax_hilite\">\n\n\t\n\t<div class=\"code\">\n\t\t<ol class=\"csharp\" style=\"font-family:monospace\"><li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">XmlElement documentation <span style=\"color: #008000\">=<\/span> DocsByReflection<span style=\"color: #008000\">.<\/span><span style=\"color: #0000FF\">XMLFromMember<\/span><span style=\"color: #008000\">&#040;<\/span><span style=\"color: #008000\">typeof<\/span><span style=\"color: #008000\">&#040;<\/span>SomeExampleClass<span style=\"color: #008000\">&#041;<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000FF\">GetProperty<\/span><span style=\"color: #008000\">&#040;<\/span><span style=\"color: #666666\">&quot;ExampleProperty&quot;<\/span><span style=\"color: #008000\">&#041;<\/span><span style=\"color: #008000\">&#041;<\/span><span style=\"color: #008000\">;<\/span><\/div><\/li>\n<li><div style=\"font: normal normal 1em\/1.2em monospace;margin:0;padding:0;background:none;vertical-align:top\">Console<span style=\"color: #008000\">.<\/span><span style=\"color: #0000FF\">WriteLine<\/span><span style=\"color: #008000\">&#040;<\/span>documentation<span style=\"color: #008000\">&#091;<\/span><span style=\"color: #666666\">&quot;summary&quot;<\/span><span style=\"color: #008000\">&#093;<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000FF\">InnerText<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000FF\">Trim<\/span><span style=\"color: #008000\">&#040;<\/span><span style=\"color: #008000\">&#041;<\/span><span style=\"color: #008000\">&#041;<\/span><span style=\"color: #008000\">;<\/span><\/div><\/li>\n<\/ol>\t<\/div>\n\n<\/div>\n\n<p>This would ouput \u201cAn example of a property\u201d, extracted from the code comments in the code fragment at the top of the article.<\/p>\n<p>The class works by locating the .XML file accompanying the assembly that defines the type or member (discovered using reflection). Then the .XML file is loaded into an XmlDocument, and the \u2018member\u2019 tags are scanned to find the one that refers to the target type or member. This tag is returned as an XmlElement which contains the free form XML that these comments can contain (e.g. including HTML markup).<\/p>\n<p>This method relies on the existence, on disk, of the generated XML. It must have the same name and location as the generated .EXE or .DLL accompanying it \u2013 with only the extension changed. This will happen by default when building with Visual Studio, once documentation is enabled (see below). If you are distributing your program and expect the distributed version to discover the comments in run time, you must also distribute the XMLs alongside the executables. This is commonly seen in any case. Note that many of the framework executables (for instance those found in C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727) are accompanied by documentation XML files.<\/p>\n<h2>How to use<\/h2>\n<p>Download the library source as a zip file <a href='http:\/\/jimblackler.com\/blog\/wp-content\/uploads\/2008\/04\/docsbyreflection_2.zip' title='The source for the DocsByReflection class library'>here<\/a>, or use Subversion to update to the very latest version <a href=\"http:\/\/svn.jimblackler.com\/jimblackler\/trunk\/Visual Studio 2005\/Projects\/DocsByReflection\">here<\/a> and <a href=\"http:\/\/svn.jimblackler.com\/jimblackler\/trunk\/Visual Studio 2005\/Projects\/DocsByReflectionDemo\">here<\/a>.<\/p>\n<p>(Updated 18\/3\/08 for bug fix &#8211; see comments).<\/p>\n<p>Load the DocsByReflectionDemo.sln to see a simple example of how to use the library. This gathers and prints information about a class type, some functions, a property and a field.<\/p>\n<h2>Using in your own code<\/h2>\n<p>In Visual Studio, set up your own project that includes XML comments.<\/p>\n<p>(Note that the XML documentation output is not enabled by default in Visual Studio. Go to your project properties, select Build, and under the Output section check the box that says XML Documentation File. It is very important that you do not change the location of the XML file or this method will not be able to locate it at run time.)<\/p>\n<p>If you have not already, add the comments in Visual Studio. By default, pressing forward slash three times when the caret is positioned before the start of an element you wish to document (such as a class or method) will insert a documentation template for you before the start of the file.<\/p>\n<p>Add the DocsByReflection project to your solution and a Reference to it from your project. Add the line \u201cusing JimBlackler.DocsByReflection;\u201d to the top of your .CS file.  The call se the functions <b>DocsByReflection.XMLFromType()<\/b> (for classes, structures and other types) and <b>DocsByReflection.XMLFromMember()<\/b> (for methods, properties and fields) to fetch XmlElement objects that represent the documentation for that type or member.<\/p>\n<p>Query the returned object to read the documentation. For instance, xmlElement[\u201csummary\u201d].InnerText.Trim(). This locates the summary node, and uses the InnerText property of XmlElement to strip out any XML formatting that may be embedded in the comment. Also, Trim() or a regular expression can strip the unwanted whitespace from the comment.<\/p>\n<h2>Comments or problems<\/h2>\n<p>If you have any comments or problems with the library, please add a reply to this blog post and I will answer them here.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C# .NET provides a standard mechanism for programmers to inline XML documentation in their programs. Classes, functions, properties and more can be augmented with comments, and the build system creates amalgamated XML files accompanying the program output. A variety of tools such as Sandcastle can build help files from the data. Visual Studio 2005 and [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-49","post","type-post","status-publish","format-standard","hentry","category-windows-applications"],"_links":{"self":[{"href":"https:\/\/jimblackler.com\/index.php?rest_route=\/wp\/v2\/posts\/49","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jimblackler.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jimblackler.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jimblackler.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jimblackler.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=49"}],"version-history":[{"count":0,"href":"https:\/\/jimblackler.com\/index.php?rest_route=\/wp\/v2\/posts\/49\/revisions"}],"wp:attachment":[{"href":"https:\/\/jimblackler.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=49"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jimblackler.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=49"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jimblackler.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=49"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}