The D-word

Documentation. Good documentation is seldom seen. We all know the nDoc tool that can massage our code comments into a nice looking reference document. But just reference documentation is usually not sufficient. You probably know from your own experience that learning to master a new library or framework takes more than just reference documentation if you want to avoid endless trail and error and searching for that API call that does what you need at that time. You need an overview of the architecture (code design) in order to relate different classes to eachother. You need a description of common usage patterns so you can get started quickly. You need… well, good documentation.

I’m not going to write about what I think is good documentation, I leave that to you to work out ;-). I just want to bring a help authoring tool under your attention that I’ve been missing (like for ever). It is packaged in an unexpected place: the Visual Studio 2005 SDK (VSIP). This SDK you use when you want to extend Visual Studio. You need to register to get it here. Microsoft ships a stripped down version of HelpStudio called HelpStudio Lite made by Innovasys. If you ever worked with Html Help workshop that ships with Visual Studio for some time now, you will find the tool familiar, if you do not have any experience, just take a look at an existing Help file and you will get most of the concepts in no time. The tool will let you generate help content that integrates into the VS.NET help viewer.

When installation of the VS.NET SDK is finished the following screen is shown. Notice that the Help Authoring tool is not installed by default and has to be installed seperatly. When I ran the installation it looked as if it didn’t work, no progress indication or whatever, but eventually the installer reported a succesfull install. So be patient.

Visual Studio SDK Installer - HelpStudio Component

When you start HelpStudio Lite a startup window is shown by default, explaining how to create a new project for instance. When creating a new project you get a choice for VS 2003 or VS 2005 compatibility. The following screenshot shows you a new help project in HelpStudio Lite.

HelpStudio New Project

Looks better that Html Help Workshop doesn’t it. I would suggest you try it and see for yourself.

nDoc Documentation

One of the things you probably want to do (at least I wanted to do) is integrate the html files generated by nDoc into your HelpStudio project. nDoc uses Html Help Workshop under the covers and HelpStudio Lite allows an import of a Html Help Workshop project file. Sweet. Not entirly. All content is wrapped in the selected HelpStudio template and this will give you double (contained) headers on each and every page. The Solution I found that works best is only import the Table of Content (ToC) of your nDoc result and just hand copy all html files into the build directory (called Default). You could add each html file to the HelpStudio project definition, but that gets labour intensive when handling large numbers and frequent updates. Each imported ToC entry has a link to an .htm file and those will get resolved during the build or you will get errors. You can move the imported ToC around to any place you fancy, without breaking the links to the content.

Deployment

So you’re done. Now you want to package your help file so others can install it (together with your library or framework). Unfortunatly the help system is pretty complex and it is not a case of just distributing a help file (like .chm). The Vistual Studio SDK site has a installer for a new VS.NET Project type that lets you build a help deployment setup (and merge module). It is called Help Integration Wizard and can be downloaded here. When you create a new VS.NET project of this type you walk through a wizard that lets you browse to the help file built by HelpStudio and create an installer for it. Note that when installing help files registering the help collection takes really long.

So I hope you find this usefull and I helped inspire you to write ‘good documentation’. This description is not as detailed as I would like due to time contraints. If you have any questions just post them as comments and I will try to get you started.

TIP: Did you know that you can export VS.NET 2005 class diagrams as .jpg image files? Right click in the designer and choose the export menu option. Now you can inculde class diagrams easily in your help files, point to the Image Files folder, add them to the help project and drag & drop them into your help Topic.

Singleton Generics [updated]

The Singleton pattern is probably the most famous pattern of all. Usually it is implemented as a behaviour of a specific class. But why not let the developer decide how to manage instance lifetimes? The new .NET 2.0 Generics feature gives us just the tools for creating these object lifetime classes.

public static class StaticInstance<T>
    where T : new()
{
    private static T _instance;
    private static object _lock = new object();

    public static T Current
    {
        get
        {
            if (_instance == null)
            {
               lock (_lock)
               {
                   if (_instance == null)
                   {
                       _instance = new T();
                   }
               }
            }

            return _instance;
        }
    }
}

This code manages one instance of Type T in a (AppDomain) static variable, your typical Singleton implementation. Any class can be used as a Singleton now, just call StaticInstance<MyClass>.Current to access the instance of your type ‘MyClass’. Beware though that being a Singleton instance has concurrency issues in that multiple threads could access that one instance of your class at the same time.

In an ASP.NET context you often have the need to have "static" information available but private to the current request. Well, simply write another instance manager class such as this one:

public static class HttpContextInstance<T>
     where T : new()
{
     private static string _typeName = typeof(T).FullName;

     public static T Current
     {
          get
          {
              Debug.Assert(HttpContext.Current != null);

              T instance = (T)HttpContext.Current.Items[_typeName];

              if (instance == null)
              {
                  instance = new T();
                  HttpContext.Current.Items[_typeName] = instance;
              }

              return instance;
          }
    }

    public static void Dispose()
    {
        IDisposable instance = HttpContext.Current.Items[_typeName] as IDisposable;

        if (instance != null)
        {
            instance.Dispose();
        }

        HttpContext.Current.Items[_typeName] = null;
    }
}

The instance is stored in the Items collection of the HttpContext, thus making the instance private to just the current web request. I’ve also included a Dispose method to dispose of the instance’s resources when the request is done (global.asax) and clear the slot in the HttpContext items collection. You could think of other implementations for storing instances in the Thread Local Storage, the logical CallContext or any other place that might be convienient to you.

Have fun,
Marc Jacobi

 



[UPDATE 14-feb-06]

 

I like to point out some of the problems that you may encounter using this approach. The following issues should be taken into account:

  1. A Type specified for T must be able to cope with the concurrency consequences of the instance class implementation. For the StaticInstance example this means that it should syncronize access to its member variables.
  2. The Type (T) must have a public default constructor and your team could use that default constructor to create their own instances. For some types this is not a real big issue for others it can introduce hard-to-track-down bugs. If your Type (T) is not designed to be instantiated more than once implement your own Current property and remove your (default) constructor(s).
  3. All team members should "know" what Type (T) is accessed by which instance class. If one member uses StaticInstance<MyClass>.Current and another uses HttpContextInstance<MyClass>.Current you’ll have 2 instances living two different lifetimes. This is a weakness that can be overcome and we will discuss next.

Because C# (generics) does not support the typedef keyword (C++: allows defining a new type using other types declaratively) the only way to simplify and hardwire a generics type is to derive from it. So if you use the following code template for instance class implementations you can fix issue 3 by deriving a new type.

public class StaticInstance<T>
    where T : new()
{
    private StaticInstance()
    {}

    public static T Current
    {
        get
        {
            // [your implementation here]
        }
    }
}

Now, say you use a static instance of MyClass in your application you can derive a new type to hardwire the T parameter. This also gives you one point of definition for the MyClass-singleton and makes it easy to transparently change the instance class backing up the singleton.

public class MyClassSingleton : StaticInstance<MyClass>
{}

I hope this update gives you a better overview of the consequenses of using this approach.
Keep the questions and suggestions coming.

Greetings,
Marc Jacobi