May 102010
 

In the first part I’ve written about creating a code generator in VS2008 to eliminate repetitive coding.

The series is divided into four parts:

Part I  – creating a Visual Studio Package

Part II (this one) – creating and registering a code generator

Part III – generating code & debugging

Part IV – creating the setup project and deploying the package

So let’s jump directly to the problem at hand:

Part II – Creating and registering a code generator class

Since VS2008 add-ins are COM objects, our code generator needs to be prepared for COM interop first. To accomplish this, we need to make it com visible and to assign it a unique identifier.

First, open up the Guids.cs file. We will add there a new constant that keeps our generator’s GUID. You can use the GUID tool in Visual Studio (Tools->Create GUID). Make sure you are using the registry format and remove the brackets. I’m not a big fan of the default coding style found in the pre-generated classes, but for simplicity I’ve kept the same style in our demo project:

// Guids.cs
// MUST match guids.h
using System;

namespace MyCompany.MyCodeGenerator
{
    static class GuidList
    {
        public const string guidMyCodeGeneratorPkgString = "51b9761b-d943-454c-9397-29e2f2b68431";
        public const string guidMyCodeGeneratorCmdSetString = "a619ef76-b153-4f88-bbc5-fda566fe7b4a";
        public const string guidMyCodeGenerator = "1432CFC5-D0C4-44cd-A937-1D476F999219";
        public static readonly Guid guidMyCodeGeneratorCmdSet = new Guid(guidMyCodeGeneratorCmdSetString);
    };
}

The next step is to mark the actual code generator as COM visible and to set it’s GUID. This can be easily done by decorating the generator class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace MyCompany.MyCodeGenerator
{
    [ComVisible(true)]
    [Guid(GuidList.guidMyCodeGenerator)]
    public class MyCodeGenerator
    {
    }
}

The code generator has to be also registered as a code generator with Visual Studio and must implement the BaseCodeGeneratorWithSite abstract base class. When you register the code generator you have two options:

  1. Register it with a human-readable name and then set it explicitly for a certain file. This method is especially useful if you have more generators that get the same input or if you don’t want to use the generator by default for a certain file. Another situation is where you don’t define a special extension but use already existing file types (XML for example).
  2. Register it as a generator for a certain file extension. This is my favorite since I can create different file extensions for different scenarios. I will go with this option in my example, but you only have to change the name from “.extension” to whatever name you want.

In the attached zip file you will see that we have a CodeGeneratorRegistrationAttribute class. This can be found in the Visual Studio SDK or you can copy it from the zip. This file is responsible with creating the necessary registry keys for our generator. To register the generator we need to decorate it using this attribute:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.TextTemplating.VSHost;
using Microsoft.VisualStudio.Shell;
using VSLangProj80;

namespace MyCompany.MyCodeGenerator
{
    [ComVisible(true)]
    [Guid(GuidList.guidMyCodeGenerator)]
    [CodeGeneratorRegistration(typeof(MyCodeGenerator), ".myfile", vsContextGuids.vsContextGuidVCSProject, GeneratesDesignTimeSource = true, GeneratorRegKeyName = ".myfile")]
    public class MyCodeGenerator : BaseCodeGeneratorWithSite
    {
        protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
        {
            throw new NotImplementedException();
        }

        public override string GetDefaultExtension()
        {
            throw new NotImplementedException();
        }
    }
}

The attribute tells Visual Studio that it should automatically use the generator for all *.myfile files. The vsContextGuids.vsContextGuidVCSProject tells Visual Studio that this generator should be used when editing a C# project. There are other options for different supported languages. The other parameters are self-explaining.

Downloads:

MyCodeGenerator-part2

 Easy creation of code generators in Visual Studio 2008 (part 2 of 4)