Jelle Druyts .NET Consultant
Just another ignorant weirdo from Antwerp, Belgium trying to make sense out of it all
Although I've argued before that Typed DataSets aren't evil, there's one thing that bothers me a lot when dealing with them in a library project: the code that gets generated doesn't contain any XML comments. In itself, that isn't so bad (after all, which useful comments could be generated from an XSD schema?), but if the project is configured to emit an XML documentation file, you get a gazillion warnings for each member that lacks a comment. I like to keep my build warning-free to avoid "known harmless warnings" from hiding "new and important warnings" (if I can first get my stuff to build without errors, at least). You could go about and put comments on the generated file manually, but any change on the dataset's schema file will trigger the code to be regenerated so you've lost all your hard work. Hence I created the following quick and dirty solution: a Visual Studio macro that runs over all members and puts a placeholder comment (containing just the member's name) on top. Anytime the code gets regenerated, just run the macro and you're set. I'm sure this should be able to run as a post-build step or something too, but if you're lazy like me (and you're a programmer too, so you're lazy by definition), you'll already be happy you got this done.
Oh, and if you're really lazy, you can use this macro to document all your members automatically - although I'd add some random word-generator to make it look just a little more convincing (to fool the QA-guys at least).
So here's the source (with special thanks to the MSDN article on XML Comment Macros):
Imports EnvDTE Imports System.Diagnostics Imports System Imports System.Xml Imports System.IO Imports System.Collections Imports System.Text Imports System.Text.RegularExpressions Public Module XmlDocumenter Public Sub InsertGenericSummaries() SetCommentsRecursively(DTE.ActiveDocument.ProjectItem.FileCodeModel.CodeElements) End Sub Private Sub SetCommentsRecursively(ByVal elements As CodeElements) For Each element As CodeElement In elements ' Get a comment block. Dim doc As XmlDocument = GetCommentXml(element) Dim summaryTag As XmlElement = doc.SelectSingleNode("/doc/summary") If summaryTag Is Nothing Then ' Create <summary> tag summaryTag = doc.CreateElement("summary") summaryTag.InnerXml = element.Name doc.FirstChild.PrependChild(summaryTag) End If SetCommentXml(element, doc) ' Recurse over members. Try SetCommentsRecursively(element.Members) Catch ex As Exception ' Ignore exceptions (quick and dirty hack to skip elements that have no Members property) End Try Next End Sub ' Code borrowed from http://msdn.microsoft.com/msdnmag/issues/05/07/XMLComments/default.aspx Private Sub SetCommentXml(ByVal element As CodeElement, ByVal doc As XmlDocument) Dim sb As StringBuilder = New StringBuilder Dim sw As StringWriter = New StringWriter(sb) Dim xw As XmlTextWriter = New XmlTextWriter(sw) Try xw.Indentation = 1 xw.IndentChar = Char.Parse(vbTab) xw.Formatting = Formatting.Indented Dim rootNode As XmlNode If element.Language = CodeModelLanguageConstants.vsCMLanguageVB Then rootNode = doc.FirstChild Else ' CSharp rootNode = doc End If rootNode.WriteContentTo(xw) Try element.DocComment = sb.ToString() Catch ex As Exception ' Ignore End Try Finally xw.Close() sw.Close() End Try End Sub ' Code borrowed from http://msdn.microsoft.com/msdnmag/issues/05/07/XMLComments/default.aspx Private Function GetCommentXml(ByVal element As CodeElement) As XmlDocument Dim doc As XmlDocument = New XmlDocument Dim xmlStr As String = element.DocComment If Not xmlStr Is Nothing AndAlso xmlStr.Trim() <> String.Empty Then If xmlStr.StartsWith("<doc>") = False Then ' Ensure single root node xmlStr = "<doc>" & xmlStr + "</doc>" End If xmlStr = Regex.Replace(xmlStr, "^(\s*<doc>\s*){2,}", "<doc>") xmlStr = Regex.Replace(xmlStr, "(\s*<\/doc>\s*){2,}$", "</doc>") doc.LoadXml(xmlStr) Else Dim rootTag = doc.CreateElement("doc") doc.AppendChild(rootTag) End If Return doc End Function End Module
Easy, effective, and ugly. Use at your own risk, it might eat your lunch sandwich.