Professional Documents
Culture Documents
SD11192
Advanced Revit Code RefactoringC# Language
Features and Design Patterns Can Help
David Echols Hankins & Anderson, Inc. Senior Programmer
Learning Objectives
Learn how to add extension methods to existing Revit API objects to add functionality
Learn how to utilize Action class delegates combined with lambda expressions to encapsulate
functionality and simplify code
Learn how to create LINQ expressions to select and process operations on groups of objects
Learn how to use design patterns to separate code responsibilities and provide uniform code
interfaces
Description
This class will explain how code based on the Revit software API can be refactored to simplify usage,
isolate functionality, and improve maintainability. Class material will cover the use of C# language
features and industry best practices to refactor code in Revit software add-ins and supporting library
modules. A detailed look will be taken at extension methods, the Action and Func delegate classes,
Microsoft LINQ, and design patterns. Specific before and after samples of code running in a production
add-in will be shown. Extension methods will be used to show how to attach functionality to the
responsible object. Delegates will be used to encapsulate code, making it less complex and more
maintainable. LINQ samples will demonstrate selecting and processing groups of objects. Finally, design
patterns will be explored that separate command functionality from the user interface and simplify the
creation of Revit elements.
Your AU Experts
Dave Echols began using CADD in 1986 with Prime Medusa. He started with AutoCAD in 1988 using
version 2.6. He has written programs for AutoCAD in Autolisp, C/C++, Visual Basic and .NET. He has been
developing add-ins for Revit since 2009 using the Revit .NET API.
1
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
Introduction
Technology does not stand still and this is certainly true with the Microsoft .NET framework and the
Revit API. Over the years, Microsoft has added new APIs and language features. The Revit API has
grown and improved every year with new feature. As add-in code is migrated from one version of Revit
to the next, it is beneficial to review the code and refactor it using new functionality in the API and new
functionality and language features in the .NET Framework. This class will present a number of ideas for
optimizing and refactoring your add-ins.
Learn how to add extension methods to existing Revit API objects to add
functionality
The Revit API provides us with a static interface for accessing the Revit application, user interface,
models and elements. Developers often create methods that extend functionality of specific classes
where the source code is not available. These methods can be added to new classes implementing the
Decorator or Adapter design patterns or added as static methods to a utility class. With the creation of
Extension Methods in the Microsoft .NET Framework, these methods can now be associated with
existing read only classes within static APIs.
2
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
if (basicInfo.IsOpenedAsCentral(e.PathName))
{
string message = "This model is a Central File. ";
message = string.Format("{0}You do not have permission to open a ", message);
message = string.Format("{0}Central File. If you want to open the ", message);
message = string.Format("{0}file, make sure the 'Create New Local'", message);
message = string.Format("{0} checkbox is checked.", message);
TaskDialogUtility.ShowTaskDialog("Central File Error", message);
e.Cancel();
return;
}
3
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
Debug.Assert(false, "Error");
return string.Empty;
}
if (!basicInfo.IsSavedInCurrentVersion)
{
string message = string.Format("This model is a \"{0}\" model. ",
basicInfo.GetVersionNumber());
message = string.Format("{0}The Revit software version is {1}. ",
message, GlobalSettings.RevitVersion);
message = string.Format("{0}This model will not be opened ", message);
message = string.Format("{0}by this version of Revit. ", message);
message = string.Format("{0}Please use the Revit version", message);
message = string.Format("{0} that matches the model.", message);
TaskDialogUtility.ShowTaskDialog("Version Mismatch", message);
e.Cancel();
return;
}
4
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
5
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
Learn how to utilize Action class delegates combined with lambda expressions to
encapsulate functionality and simplify code
Delegates have been in the .NET Framework from the beginning. With the release of .Net Framework
3.5, Action and Func delegates were added along with Lambda expressions. These features can be
difficult to understand and use but can provide developers with ways to encapsulate functionality and
simplify their code. The following section will cover the transition of a standard, well used code block in
Revit to an extension method that uses an Action delegate and lambda expression
6
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
FIGURE 1: REFACTOR CODE WITHIN THE TRANSACTION BLOCK INTO A SINGLE METHOD
7
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
8
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
9
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
Learn how to create LINQ expressions to select and process operations on groups of
objects
LINQ stands for Language Integrated Query. It made its debut the release of .Net Framework 3.5 and is
closely tied to Lambda expressions. The LINQ API allows the use of two different syntax forms; LINQ
Query syntax and LINQ Method syntax. Both forms will be covered in this class. Query syntax looks very
similar to standard SQL statements and is transformed by the compiler into the Method syntax. The
Method syntax provides a number of method calls that operate on collections of objects. These
collections are derived from the implementation of the IEnumerable<T> interface of the Enumerable
class in the System.Collections.Generic namespace. Interestingly the LINQ methods are themselves
extension methods.
10
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
11
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
12
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
13
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
Learn how to use design patterns to separate code responsibilities and provide
uniform code interfaces
The book Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson
& Vlissides was first published in 1995. Design patterns in software architecture have been around for
over 2 decades. From the book: A design pattern names, abstracts and identifies the key aspects of a
common design structure that makes it useful for creating a reusable object-oriented design.. 1
It is safe to say that the developers of the Revit API have used design patterns in the implementation of
the API. Using a tool like Red Gates .Net Reflector, it is easy to spot these design patterns. Proxies are
used to handle unmanaged resources and Adapters are used to transform the interface presented by
the proxy objects into the public interface presented in the API. The
Autodesk.Revit.DB.ExtensibleStorage namespace uses the Builder pattern to build fields and schemas.
Developers using the Revit API can also use design patterns in their code.
14
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
interacts with Revit to produce the PDF files. This is a key benefit of using the factory pattern
with the command pattern. Internally, Revit probably uses a similar mechanism to manage the
loading and execution of external commands.
15
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
16
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
private CommandFactory()
{
Commands = new List<ICommand>();
RegisteredCommands = new List<ICommand>();
}
17
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
such as the TextNote element are more complex. The following figure shows how the Create
method works by providing a clean wrapper for creating a DetailLine.
18
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
19
Advanced Revit Code RefactoringC# Language Features and Design Patterns Can Help
References
The following references were used in the preparation of this handout.
1. Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1995). Introduction: Section 1.1. In Design
patterns: Elements of reusable object-oriented software (p. 3). Reading, MA: Addison-Wesley.
20