asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Documenting .NET Assemblies
By Robert Chartier
Rating: 3.0 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    Reflection is a feature in .NET that automatically produces documentation for assemblies.

    Note documentation can be produced from the source code with XML comments simply by using the "/doc" parameter with the C# compiler, but there is no equivalent with the VB .NET compiler. Or "Tools, Build Comment Web Pages..." in Visual Studio .NET could be used. Both of these assume that the full source code is available for the projects that need documenting. If these are available, I would recommend that course of action first.

    If the source code that produced the assemblies is not available, then this tool is a must. Let's start with an overview of Reflection, and then analyze the tool's code.

  • download source code for tool

    What Is Reflection?

    Reflection is a way to discover information about assemblies in .NET. The term "assembly" refers to any sort of compiled .NET file (i.e., Console/Windows executable (EXE), or a library (DLL)).

    Within .NET, everything created is within a class (or "Type") of some sort, and is the information that can be discovered. Some of the more basic "Types" are a string, an integer, etc. And assemblies can contain more than one Type. Within each Type we can retrieve the details, such as a list of all the members (methods, properties, etc) and each member's parameter information. Lastly, Reflection provides the ability to dynamically create and invoke Types. To learn more, see System.Reflection Namespace on MSDN http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemReflection.asp.

    The Reflection Tool

    The tool currently consists of a simple DOS command-line executable that consumes the custom object (Documenter), which handles the reflection of our assemblies. Provide a path to either the assembly's folder or to the exact assembly in question, and provide the location of the folder to which the documentation should be sent. The tool will then process the file(s) and output the necessary documentation in XML format. I prefer XML because of its flexibility and the ability to simply add an XSL Transformations (XSLT) style sheet to convert the XML into any format, such as HTML.

    The Console Application

    The console application ensures that it receives all the appropriate bits of data via the command line. Again, in order for the application to run smoothly, the location of the assembly(s) to document and the location to output the XML documentation is needed. For debugging, the capability of logging the process of the reflection to another file has been added, but this portion of the code will not be discussed here.

    The code uses a simple command-line parameter parsing loop. It will simply loop for each argument passed into the application and attempt to match each item against a known list of argument parameters.

    
          foreach(string arg in args) {
            if(arg.Length>3) {
              if(arg.Substring(0,3)=="/s:")
                asmpath=arg.Substring(3);
              if(arg.Substring(0,3)=="/o:")
                outputpath=arg.Substring(3);
              if(arg.Substring(0,3)=="/l:")
                loggingtype=arg.Substring(3);
              if(arg.Substring(0,3)=="/p:")
                logpath=arg.Substring(3);
            } else if(arg.Length==2){
              if(arg.Substring(0,2)=="/?") 
                if(cont)ShowHelp();
              cont=false;
            } else {
              if(cont)ShowHelp();
              cont=false;
            }
          }
    
    
    Here's an explanation of each parameter.

    /s:{PATH/FILE}
    Specifies the location of the source assembly(s).
    Takes the file name or directory name.
    If it is a directory, it will recursively search all subdirectories and load in all assemblies.

    /o:PATH
    Specifies the location of the report.
    This is the output XML document.

    /l:[Console][File]
    Specifies the type of logging.
    If File is used, specify the file to log to.

    /p:FILE
    When using file logging, specify the path to the log file.

    /?
    Help

    Now that all the appropriate parameters are loaded in, the next step is to determine if there is enough data to continue processing. Within the source, I have initialized the variable which will hold our path to look for the assemblies so it points to the current path of the executing console application.

    
    string asmpath=System.Reflection.Assembly.GetExecutingAssembly().Location;
    
    
    Therefore, the only required piece of information that is needed to continue is the path to the output location, and if this piece is missing, Help shows. Let's build the documentation:
    
    if(outputpath=="") { 
      if(cont)ShowHelp();
      cont=false;
    } else {
      if(cont) {
        AssemblyDocumenter.Documenter doc;
        if(loggingtype.ToUpper()=="FILE" && logpath!="") 
          doc = new AssemblyDocumenter.Documenter(asmpath, outputpath, new AssemblyDocumenter.FileLog(logpath));
        else
          doc = new AssemblyDocumenter.Documenter(asmpath, outputpath, new AssemblyDocumenter.ConsoleLog());
      }
    }
    
    

    The Assembly Documentation Library

    The driving class within this library is the "Documenter" class, and the first thing it must do is load the appropriate files into memory. It uses another class, "Files", which determines if it was given a file or a folder. If it was given a folder, it scans that folder and any subfolders for assemblies. Here is our Files class:

    
      public class Files{
        public System.Collections.ArrayList AsmFiles { get{return asmFiles;} }
        private System.Collections.ArrayList asmFiles = new System.Collections.ArrayList();
        private System.Collections.ArrayList notAsmFiles = new System.Collections.ArrayList();
        private AssemblyDocumenter.Logger logger;
        System.Boolean log=false;
        public Files(string asmlocation, AssemblyDocumenter.Logger Logger, System.Boolean Log) {
          logger=Logger;
          log=Log;
          if(System.IO.File.Exists(asmlocation)) {
            //just document this one single assembly
            asmFiles.Add(System.Reflection.Assembly.LoadFrom(asmlocation));
            if(log) logger.Log("Loaded:" + asmlocation +"\n");
          } else if(System.IO.Directory.Exists(asmlocation)) {
            //document entire folder
            LoadFiles(asmlocation);
            if(log) logger.Log("Done Loading "+Convert.ToString(asmFiles.Count)+" Files.\n");
          } else {
            //do nothing
          }
        }
        public void LoadFiles(string location) {
          //first get a list of all the directories
          //now load all the files in
          foreach(string file in System.IO.Directory.GetFiles(location,"*.dll")) {
            try {
              asmFiles.Add(System.Reflection.Assembly.LoadFrom(file));
              if(log) logger.Log("Loaded:" + file +"\n");
            } catch(Exception e) {
              notAsmFiles.Add(file);
              if(log) logger.Log("Could not load:" + file +"\n");
            }
          }
          foreach(string dir in System.IO.Directory.GetDirectories(location)) {
            LoadFiles(dir);
          }
        }
      }
     
    
    Notice it is only looking for DLL files. This may be modified to allow the user to specify the type of files to load in by adding another command-line parameter.

    The most important line from the above source listing is:

    
    asmFiles.Add(System.Reflection.Assembly.LoadFrom(file));
    
    
    Once a file that appears to be an assembly is found, the application attempts to load it into memory using reflection. The LoadFrom() method will actually return a System.Reflection.Assembly object, which is a representation of that entire assembly in memory. This is the start of the reflection process. Notice the error-catching while the assembly loads. It adds those files to a notAsmFiles array list.

    Once this class is finished loading, it will have an ArrayList object that contains all of the available assemblies that can now work within the Documenter class. We can see the call to the Files class within the "BuildDocs" method:

    
    files = new AssemblyDocumenter.Files(AssemblyLocation, logger, log);
    
    
    Since the collection of files is complete, the application will reflect each one and create the necessary documentation. We will also need to keep track of each assembly and its documentation's location. The tool generates an index file from which to drive the documentation.

    Notice that this method is littered with XML, which makes it difficult to read. I will pull out the important pieces and explain each one.

    First are the two StringBuilders. I used these to send and build up the XML content for the index file and each individual assembly documentation file. The StringBuilder class is well documented in the .NET Framework SDK (see http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemTextStringBuilderClassTopic.asp).

    At the core of the documentation process is a loop to iterate every assembly within our ArrayList object:

    
    foreach(System.Reflection.Assembly assembly in files.AsmFiles) {
    
    
    Within each assembly could exist many Types, so we must loop on each Type found:
    
    foreach(System.Type type in assembly.GetTypes()) {
    
    
    And within each Type are a variety of items to pull out, some of which include constructors, event information, methods, properties, interfaces, and other miscellaneous pieces of data. Skim over the code within the loop, and look at how reflection is used to pull out all of the details, including the methods I call to help out in reflecting each item. Take time to compile and test the Documenter against your assemblies, and review the XML it produces.

    Conclusion

    The basics of Reflection are straightforward and easy to use. Some of the more advanced items, like dynamically creating and invoking types, are something to review also. Being aware and having these tools at your disposal will always be beneficial.

    Build on top of the code provided here to fill in the pieces that I intentionally left out. For example, I have not included any code to reflect any custom attributes that our types may have. Take time to implement this feature in your version of the documenter.

    The last piece of this project would be to make the documentation more presentable for the end user. The XML format is adequate for some, but most prefer an HTML interface to interact with. If someone decides to create an XSLT document to convert the XML to HTML please forward it so it can be posted here.

    About the Author

    Robert Chartier has developed IT solutions for more than nine years with a diverse background in both software and hardware development. He is internationally recognized as an innovative thinker and leading IT architect with frequent speaking engagements showcasing his expertise. He's been an integral part of many open forums on cutting-edge technology, including the .NET Framework and Web Services. His current position as vice president of technology for Santra Technology (http://www.santra.com) has allowed him to focus on innovation within the Web Services market space.

    He uses expertise with many Microsoft technologies, including .NET, and a strong background in Oracle, BEA Systems, Inc.'s BEA WebLogic, IBM, Java 2 Platform Enterprise Edition (J2EE), and similar technologies to support his award-winning writing. He frequently publishes to many of the leading developer and industry support Web sites and publications. He has a bachelor's degree in Computer Information Systems.

    Robert Chartier can be reached at rob@aspfree.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Jul 28, 2005 - N-Tier Web Applications using ASP.NET 2.0 and SQL Server 2005 - Part 2
    In the second part of his series on building N-tier web applications using ASP.NET 2.0 and SQL Server 2005, Thiru Thangarathinam covers the business logic and user interface layers. In the process, he also examines some new features in ASP.NET 2.0 that greatly simplify the development process.
    [Read This Article]  [Top]
    Jul 14, 2005 - An Innovative Technique for Creating Reusuable Page Templates in ASP.NET 1.x
    Code reusuability is one of the major goals of any good object-oriented programmer. While the ASP.NET framework has made code reusuability easier and more elegant than it was in classic ASP, one area where reusuability could be improved is at the UI level. This article outlines a technique that you can use in ASP.NET 1.x that allows every page in your web application to inherit not only the functionality of a base page, but its UI as well.
    [Read This Article]  [Top]
    Jun 23, 2005 - Monitoring SharePoint Usage through an ASP.NET Web Application
    In this article, Gayan Peiris looks at creating an ASP.NET web application that will display the usage details of a selected SharePoint site. Building such an application enables SharePoint administrators to gather all SharePoint usage data from a central location.
    [Read This Article]  [Top]
    May 12, 2005 - Retrieving SharePoint Site Information in an ASP.NET Web Application
    In this article, Gayan Peiris examines using the SharePoint Object Model to access SharePoint site information from an ASP.NET web application. It should be of particular interest to SharePoint administrators who can use the included code as a starting point for development of their own web-based SharePoint administration application.
    [Read This Article]  [Top]
    Dec 23, 2004 - Automated Deployment for Side By Side .NET Web Apps for Visual Studio .NET 2003
    In this article, David Every outlines a step-by-step account of how he solved the problems he encountered while implementing an auto-deployment process. He also describes how to create a stable process for automated remote .NET deployment featuring "side-by-side" capability.
    [Read This Article]  [Top]
    Sep 29, 2004 - Developing Web Parts with ICellConsumer Interface
    Most default SharePoint Server Web Parts can be connected across organizations. The third article in this series shows how to develop connectable Web Parts that consume information provided by other Web Parts.
    [Read This Article]  [Top]
    Aug 10, 2004 - Implementing and Promoting Daily Builds
    Automatic daily builds is a well known software engineering best practice. This article introduces a strategy for implementing and promoting daily builds and offers tips and tricks for preventing and fixing breaks.
    [Read This Article]  [Top]
    Jun 21, 2004 - Using Open Source .NET Tools for Sophisticated Builds
    Building an application can be more than pressing F5. With an increasing number of quality packages being released, developers for the .NET platform now have options to create a very sophisticated build process. Aaron Junod describes a sample build environment and shows how a number of tools can work together to make reliable, predictable, and value-added builds.
    [Read This Article]  [Top]
    Jun 24, 2003 - Programming for the Palm Part 1 - Creating the Palm Application
    The first part of this three part series walks through the process of creating a mobile blog application using a BASIC development environment for Palm OS devices called NS Basic. Subsequent articles will focus on synchronizing the data to the desktop using C# and creating an installer.
    [Read This Article]  [Top]
    Jun 18, 2003 - Online Database Functions Testing Tool
    This short article provides source code for a classic ASP online database functions testing application and shows how to configure and use the tool for either SQL Server or Oracle.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers