Copyright © 2003 Atif Aziz, Skybow AG
This documentation applies to Visual Studio Code Generator Shim v1.0.4306.0 (BETA).
Visit the GotDotNet Workspace of this project.
The VS Code Generator Shim is a generic custom tool for Visual Studio .NET 2002 and 2003 that enables code generators to be written easily and quickly in just about any .NET language and using familiar .NET Framework constructs. A standard custom tool designed for Visual Studio must use COM interoperability (when written in managed code) and register with the IDE to be fully operational, but the shim helps eliminates these requirements entirely. You only need to create a class and expose a single method to write a code generator now. What is more, the code generator can be completely idependent of Visual Studio releases.
Visual Studio .NET 2002 and 2003 allow code generators to be written for files in
a project. A code generator is responsible for taking an input file and transforming
it into source code in the language of the project. In Visual Studio .NET terminology,
these code generators are called custom tools. A good example of a custom tool is
the MSDataSetGenerator
that ships with Visual Studio .NET. It takes
an XSD file as its input and uses the
schema described within to generate a strongly-typed
DataSet
class in either C# or VB .NET (or whatever happens to be
language of the project). To associate a custom tool with any file in a project,
you simply activate the Property window for the file and set the
tool's friendly name into the
Custom Tool property.
Custom tools are fundamentally COM objects that implement the IVsSingleFileGenerator
interface and therefore can be written in a .NET language that supports
COM Interop. A custom tool must be registered as a COM compontent in the system
as well as a code generator with Visual Studio .NET.
The purpose of the VS Code Generator Shim is to simplify development of code generators for Visual Studio .NET by providing a completely managed solution that does not require COM Interop or registration with Visual Studio .NET. To achieve this, the VS Code Generator Shim simply registers itself as the COM object and the custom tool with the IDE and then delegates the real work to a downstream managed code generator. The only requirement is that the input file must be in XML.
To tell the VS Code Generator Shim (referred to simply as shim from this point forth) which downstream code generator to invoke, the input file must be in XML and contain the following XML processing instruction:
<?codegen type="..."?>
The codegen
processing instruction must appear somewhere before
the root element in the XML document, otherwise the shim throws an exception. And
although it can be specified more than once in the same document, only the first
one is ever used.
The type
parameter of the codegen
processing instruction
specifies the assembly-qualified type name of the code generator to use. If the
assembly containing the code generator does not have a strong-name or it is not
installed in the
Global Assembly Cache (GAC) , then you can omit the assembly specification
from the type
parameter and instead provide the fully-qualified
path of the assembly file in a separate parameter called codeBase
.
The downside of this, however, is that the path gets hard-wired into the XML file.
The shim therefore allows the use environment paths. This is done leaving just the
assembly file name and extension in the codeBase
and specifying
an additional boolean parameter on the processing instruction called usePath
.
If the value of usePath
is 1
or true
(instead of 0
or false
; the deftault) then the
shim will try to locate the assembly by appending its files name to the list of
semi-colon delimited paths in the CODEGENPATH
environment variable.
Once the assembly is successfully loaded, the shim goes on to instaniate an instance
of the type. It then checks if the downstream code generator supports the Skybow.CodeGeneration.ICodeGenerator
interface. If it does, then it calls its sole Generate
method,
passing in a context, a text reader to parse the input and a text writer to write
the code.
The ICodeGenerator
interface is defined as follows:
public interface ICodeGenerator { void Generate( IContext context, TextReader inputReader, TextWriter outputWriter); }
Public Interface ICodeGenerator Sub Generate( _ ByVal context As IContext, _ ByVal inputReader As TextReader, _ ByVal outputWriter As TextWriter) End Interface
If the above interface is not implemented by the code generator, then the shim uses
late-binding. This latter scenario is designed to favor developers who wish to write
code generators with minimum dependencies. Implementing Skybow.CodeGeneration.ICodeGenerator
adds a dependency on the SkybowVsCodeGenerator
assembly. When late-binding,
the shim looks for a public method called Generate
that has the
following signature:
public void Generate( IDictionary contextProperties, TextReader inputReader, TextWriter outputWriter)
Public Sub Generate( _ ByVal contextProperties As IDictionary, _ ByVal inputReader As TextReader, _ ByVal outputWriter As TextWriter)
If the method is called differently, you can specify it using the entryPoint
parameter on the codegen
instruction.
To use the code generator from Visual Studio .NET, the input XML file must be associated
with the Skybow.CodeGen
custom tool. Given this, writing a custom
tool or code generator is now as simple as creating a class that exposes the
Generate
method (or alternatively implementing Skybow.CodeGeneration.ICodeGenerator
).
The parameters of the Generate
method are as follows:
Parameter | Type | Description |
---|---|---|
contextProperties |
IDictionary |
A name-value pair dictionary of context properties for the code generator. |
context |
IContext |
A name-value pair dictionary of context properties for the code generator. The
Properties property contains the actual dictionary whereas the context
parameter itself is the context object. |
inputReader |
TextReader |
The reader object for reading the input source text. |
outputWriter |
TextWriter |
The writer object to be used by the generator to write the output source code text. |
The context properties dictionary is filled in by the shim for the code generator in case it wishes to use any. The currently set of defined context properties are show here:
Property (Key) | Description |
---|---|
urn:schemas-skybow-com:codegen:DefaultNamespace |
A string containing that contains the default namespace associated with the Visual Studio project. |
urn:schemas-skybow-com:codegen:InputFilePath |
A string containing that specifies the path to the input file. |
urn:schemas-skybow-com:codegen:Language |
A string that specifies the target language in which the code should be generated.
The currently recognized values are: C# , VB and
VJ# . This string is case-sensitive. |
To be completed ...
There are 5 sample code generators that ship with the shim, each showing a different technique to leverage code generation:
Console.WriteLine
to output a message. The text of the message
is configurable and is taken from the input XML file. This generator uses the CodeDom technology to produce the code.ServiceDescriptionImporter
class from the .NET
Framework to do the real work. The location of the WSDL file for which to generate
the client proxy code is taken from the input XML file.XsdClassesGenerator
, except
instead of passing the /classes
switch to XSD.EXE, it passes
/dataset
to generate a typed DataSet
class.All of the code generators can be run in Microsoft Visual Studio .NET 2002 or 2003.
See discussion of Custom Tools in Top Ten Cool Features of Visual Studio .NET Help You Go From Geek to Guru.