the background of Figure 13-12. Double-clicking this error opens the details for the error, in which
you can find your comment in the Notes section.
256 .
chaPter 13 code conSiSTency ToolS
fiGure 13-12
The third error in Figure 13-11 points out that the MessageBoxOptions parameter hasn’t been
specified. In this case, this is by design so you want to exclude the error in source. To do this, add
the SuppressMessage attribute to the method calling MessageBox.Show as in the following code.
The parameters supplied are the Category, CheckId, and Name of the error as found in the Message
Details window for the error.
c#
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Globalization”,
“CA1300:SpecifyMessageBoxOptions”,
Justification=“MessageBoxOptions omitted intentionally“)]
private void SayHelloButton_Click(object sender, EventArgs e){
MessageBox.Show(“Hello World!“);
}
Vb
<System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Globalization”,
“CA1300:SpecifyMessageBoxOptions”,
Justification:=“MessageBoxOptions omitted intentionally“)>
Private Sub SayHelloButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles SayHelloButton.Click
MessageBox.Show(“Hello World!“)
End Sub
To get FxCop to notice the SuppressMessage attribute, you also need to set the CODE_ANALYSIS
compilation flag. You do this by adding the CODE_ANALYSIS keyword to the Custom Constants
textbox in the Advanced Compile Options dialog (from the Compile tab of the project
Coding standards .
257
properties page) for VB, or by adding the same keyword to the Conditional compilation symbols
textbox (on the Build tab of the project properties page) for C#. After saving, rebuilding your
application and rerunning the Analysis (note that you don ’t need to restart or even reload the project
within FxCop) you will see that the error has been moved to the Excluded in Source tab. Again,
double-clicking the error and going to the Notes tab reveals the contents of the Justification
parameter specified as part of the SuppressMessage attribute (you may need to import the System
.Diagnostic.CodeAnalysis namespace to use this attribute).
You have two other ways to control how FxCop is applied to your code. The first is to use the
Targets window to enable/disable the running of rules on sections of code. The left image of
Figure 13-13 shows the Targets window with the SourceSafeSample expanded to view the
IsAdminUser property. In this example the checkboxes have been unchecked to indicate that rules
should not be run on this property.
fiGure 13-13
In the right image of Figure 13-13 you can see the Rules list that has been expanded to show the
Mark assemblies with NeutralResourcesLanguageAttribute rule. This was the rule that was
generating a warning in Figure 13-11 and has been unchecked to prevent this rule being used in the
analysis.
Excluding an entire rule is generally not a good practice because it can hide
errors at a later date. For example, if an assembly is added to the project, this
rule will never be run on that assembly, even though it may be important for
the rule to be applied to that assembly.
FxCop comes with a large selection of rules that may or may not align with the way you and your
team write code. If you want to enforce your own standards you can extend the default set of rules
by writing your own, using the FxCop SDK that comes with FxCop as a reference.
258 .
chaPter 13 code conSiSTency ToolS
style using stylecop
Although FxCop is great for picking up issues
relating to the way that you write your code,
it doesn’t do much for maintaining a common
coding style. For this, you need to download
and install StyleCop, which is available by
searching for StyleCop on the MSDN code gallery
(http://code.msdn.microsoft.com). Unlike
FxCop, which runs as a standalone tool, StyleCop
integrates into the Visual Studio 2010 IDE,
allowing you to invoke the analysis from Solution Explorer, as shown in Figure 13-14.
After running StyleCop, you will see that any issues are by default reported as warnings, as
in Figure 13-5. If you want to enforce StyleCop you need to tell Visual Studio 2010 to treat
warnings as errors.
fiGure 13-14
fiGure 13-15
As with FxCop you can elect to ignore rules via the StyleCop settings, or suppress rules in specific
instances by adding the SuppressMessage attribute. You will most likely have to right-click the
warning and select Show Error Help to access the Category, CheckId, and Name of the warning
you are going to suppress. The format for the SuppressMessage arguments are (“[Category]”,
“[CheckId]:[Name]”), so for example, (“Maintainability Rules”, “SA1400:
AccessModifierMustBeDeclared“).
code contracts
The last tool that we’re going to cover is Microsoft Code Contracts, which at the time of writing is
currently available as a download from the Code Contracts project at Microsoft DevLabs (http://
msdn.microsoft.com/devlabs). After downloading and installing this tool, you will need to restart
Visual Studio 2010 to get the IDE extensions to appear. Once you have reopened your project you
will also need to add a reference to Microsoft.Contracts, which should be on the .NET tab of the
Add References dialog (right-click the project in Solution Explorer and select Add References).
Now you can add contracts in the form of pre- and post-conditions to your code. In the
following example you can see a pre-condition set for the Divide method that requires (using
Coding standards .
259
Contract.Requires) that the denominator is not zero. Similarly, there is a post-condition that
ensures (using Contract.Ensure) the Add method increments the field currentValue by the correct
amount.
c#
private double currentValue;
private double Divide(double denominator){
Contract.Requires(denominator != 0);
return currentValue / denominator;
}
private void Add(double valueToAdd){
Contract.Ensures(currentValue == Contract.OldValue(currentValue) + valueToAdd);
// Do nothing so that contract fails
}
private void InvokeDivision(){
currentValue = 7.0;
double c = Divide(0); // fails validation because b == 0
}
private void InvokeAddition(){
currentValue = 13.0;
Add(6);
}
Vb
Private currentValue As Double
Private Function Divide(ByVal denominator As Double) As Double
Contract.Requires(denominator <> 0)
Return currentValue / denominator
End Function
Private Sub Add(ByVal valueToAdd As Double)
Contract.Ensures(currentValue = Contract.OldValue(currentValue) + valueToAdd)
‘ Do nothing so that contract fails
End Sub
Private Sub InvokeDivision()
currentValue = 7.0
Dim c = Divide(0.0) ‘fails validation because b == 0
End Sub
Private Sub InvokeAddition()
currentValue = 13.0
Add(6)
End Sub
With these contracts in place, you need to enable contract verification via the Code Contracts
tab of the project properties page, as shown in Figure 13-16. Now when you build and run your
application, you will see an Assert dialog thrown when either InvokeDivision or InvokeAddition
are called, reflecting the contract that has been violated.
260 .
chaPter 13 code conSiSTency ToolS
fiGure 13-16
Here you can see that run time checking has been enabled and that it has been set to raise an Assert
on Contract Failure. If you disable this option a ContractException is raised instead, which you
can handle via code.
In Figure 13-16, there is space in the middle for Static Checking options. These
are available if you install Code Contracts for Visual Studio 2010 Premium and
above. This enables further static checking to attempt to ensure contracts are not
violated at design time, rather than waiting for them to fail at run time.
suMMary
This chapter demonstrated Visual Studio 2010’s rich interface for using a source control repository
to manage files associated with an application. Checking files in and out can be done using the
Solution Explorer window, and more advanced functionality is available via the Pending Changes
window.
Although SourceSafe is sufficient for individuals and small teams of developers, it has not been
designed to scale for a large number of developers. It also doesn’t provide any capability to track
summary .
261
tasks or reviewer comments against a set of changes. Chapter 57 discusses the advantages and
additional functionality that is provided by Team Foundation Server, an enterprise-class source
control repository system.
This chapter also introduced you to FxCop, StyleCop, and Code Contracts, which can all be used
to improve the quality, reliability, and consistency of your code. Their close integration into or with
Visual Studio 2010 makes them invaluable tools for development teams of any size.
14
Code Generation with T4
what’s in this chaPter?
.
Using T4 templates to generate text and code
.
Troubleshooting T4 templates
.
Creating Preprocessed T4 template to include templating in your
projects
Frequently, when writing software applications you will come across large areas of boilerplate
code in which the same pattern is repeated over and over. Working on these areas of code
can be time-consuming and tedious, which leads to inattention and easily avoidable errors.
Writing this code is a task best suited to automation.
Code generation is a common software engineering practice where some mechanism, rather
than a human engineer, is used to write program components automatically. The tool used
to generate the code is known as a code generator. A number of commercial and free code
generators are available in the market from the very general in nature to those that are
targeted toward a very specific task.
Visual Studio 2010 includes a code generator that can generate files from simple template
definitions. This code generator is known as the Text Template Transformation Toolkit, or
more commonly, T4.
T4 was originally introduced as part of the Domain Specific Languages Toolkit, which was
an add-in for Visual Studio 2005. T4 was included out of the box in Visual Studio 2008 but it
was poorly documented and there were very few hints in the IDE that it existed. Visual Studio
2010 makes T4 a first-class citizen so that Text Template is now one of the options in the
File . New dialog.
264 .
chaPter 14 code generATion WiTh T4
This chapter explores the creation, configuration, and execution of T4 templates. You also see how to
troubleshoot templates when they go wrong. Finally, you create a Preprocessed Text Template that allows
you to create reusable T4 templates that you can easily call from your own code.
creatinG a t4 teMPlate
In previous versions of Visual Studio, creating a new T4 template was a hidden feature that involved
creating a text file with the .tt extension. In Visual Studio 2010 you can create a T4 template
simply by selecting Text Template from the General page of the Add New Item dialog shown in
Figure 14-1.
fiGure 14-1
When a new T4 template is created or saved,
Visual Studio displays the warning dialog shown
in Figure 14-2. T4 templates execute normal .NET
code and can theoretically be used to run any sort
of .NET code. T4 templates are executed every
time they are saved so you will likely see this
warning a lot. There is an option to suppress
these warnings but it is global to all templates
in all solutions. If you do turn it off and decide you’d rather have the warnings, you can reactivate
them by changing Show Security Message to True in Tools . ptions . Text Templating.
fiGure 14-2
Once the template has been created it appears in the Solution Explorer window as
a fi le with the .tt extension. The template fi le can be expanded to reveal the fi le
it generates. Each template generates a single fi le, which will have the same name
as the template fi le itself and a different extension. Figure 14 - 3 shows a template fi le and the fi le it
generates in Solution Explorer.
fiGure 14 - 3
The generated fi le is initially empty because no output has been defi ned in the template fi le. The
template fi le is not empty, however. When it is fi rst generated it contains the following two lines:
< #@ template debug="false" hostspecific="false" language="C#" # >
< #@ output extension=".txt" # >
Each of these two lines is a T4 directive , which controls some aspect of the way in which the
template is executed. T4 directives are discussed later in the chapter but there are a few things of
interest here. The template directive contains an attribute specifying which language the template
will use. Each template fi le can include code statements that are executed to generate the fi nal fi le
and this attribute tells Visual Studio which language those statements will be in.
If you are using VB you need to enable Show All Files for the project to see the
generated fi le.
The template language has no impact on the fi le being generated. You can
generate a C# fi le from a template that uses the VB language and vice versa. This
defaults to the language of the current project but can be changed. Both C# and
VB templates are supported in projects of either language.
The second thing of note is the extension attribute on the output directive. The name of the
generated fi le is always the same as that of the template fi le except that the .tt extension is replaced
by the contents of this attribute. If Visual Studio recognizes the extension of the generated fi le,
it treats it the same as if you had created it from the Add New Item dialog. In particular, if the
extension denotes a code fi le, such as .cs or .vb , Visual Studio adds the generated fi le to the build
process of your project.
When the output extension of a template is changed, the previously generated
fi le is deleted the next time the template is run. As long as you are not editing the