Outputting Code - Understanding Types
(Page 13 of 19 )
Types in .NET is a general term referring to classes, enums, data types, structures, and interfaces. Type declarations in the CodeDOM graph are represented as objects of the CodeTypeDeclaration class. Use the IsEnum, IsStruct, and IsInterface properties to indicate the category if it isn’t a class (which is the default).
CAUTION: CodeTypeMember has an Attributes property for values of the MemberAttributes enumeration. These values are appropriate for members and aren’t intended for use on types. The CodeTypeDeclaration class also contains a TypeAttributes property for values of the TypeAttributes enumeration that are appropriate for types. Be sure you use only TypeAttributes for the CodeTypeDeclaration to avoid later compiler errors. It may seem odd that the CodeTypeDeclaration has both Attributes and TypeAttriubutes, but within the inheritance hierarchy, CodeTypeDeclaration derives from CodeTypeMember. This inheritance design is essential to let you nest types as members within other types but leads to this strange artifact.
Understanding Members Types contain members. For example, your .NET code might have a Book type (class or structure) that has a Price property and a SetInventory method as two of its members. When you’re building a CodeDOM graph, you specify the kind of member to create by the class you instantiate. These classes are shown in Figure 3-4, and all derive directly or indirectly from the CodeTypeMember. To keep the figure focused on the overall design, Figure 3-3 doesn’t show that CodeEntryPointMethod, CodeConstructor, and CodeTypeConstructor actually derive from CodeMemberMethod. CodeMemberMethod derives from CodeTypeMember. (See footnote 7)
Footnote 7. All of the objects contained in the CodeCompileUnit ultimately derive from CodeObject.
CAUTION: The CodeDOM is all about outputting syntax. It isn’t about correct code. So, in building the CodeDOM graph, you can reference objects and methods that don’t exist. You have to output your code and let the compiler find out where you messed up. For example, a constructor isn’t valid on an interface, but the CodeDOM won’t complain if you provide one. However, the compiler will raise errors.
Understanding Statements Members contain statements. The statement in code corresponds to the sentence in human language. This is the core of meaning. And just like human sentences, code statements perform different tasks. (See footnote 8.) The CodeDOM includes many different types of statements that perform different tasks. Looking at Figure 3-4, you’ll see 14 different statement types. There’s a comment statement, five statements to control program flow, three for exception handling, two for attaching and removing event handlers, one for variable declarations, one for assignments, and one for using expressions as statements. All statements reside in methods.
Footnote 8. In human languages, sentences can be commands, questions, informational statements, opinions, quotations, and so on.
NOTE: You often have declarations at the top of .NET classes. These may appear to be statements, but they’re actually fields. Fields are members of the class, and statements can only appear within method bodies. |
Understanding Expressions
Statements are made up of expressions. Expressions break the meaning of code down to the next level. The expression is similar to a clause in a human language. I can say “Understanding Expressions,” and I haven’t written a complete sentence, but I’ve placed words together in a way that conveys meaning. Within the CodeDOM, a clause may be the reference to a specific variable, invoke an expression, access language operators such as casts or GetType (typeof in C#), and so on. Figure 3-4 illustrates the range of expression types available.
Figure 3-4. Statements and expressions supported by the CodeDOM.
In human language, a clause might stand alone and be grammatically correct in some contexts. For example, I used “Understanding Expressions” as the main title of this section. The same thing occurs within .NET. An example of an expression that can stand alone is invoking a method that doesn’t return a value—calling a Sub in VB. The expression needs a container, and you can use the CodeExpressionStatement class as a container for these simple expressions.
NOTE: Where the CodeDOM expects an expression, it’ll accept any of the expression types, but the output code may not compile. |
Most statements use expressions. The statements that don’t use expressions are gray in Figure 3-4. In addition to their use in statements, expressions often use other expressions. For example, an expression could call a method that took an argument that was itself the return value of another method:
obj.MethodA(obj.MethodB(j))
The code to create this line in the CodeDOM is a bit intimidating, but it illustrates how expressions work within the CodeDOM. A CodeExpressionStatement holds the expression. The expression is a CodeMethodInvokeExpression that invokes MethodA on the variable obj. The single parameter passed is another CodeMethodInvokeExpression that invokes MethodB on the variable obj. The code is as follows:
entry.Statements.Add( _
New CodeExpressionStatement( _
New CodeMethodInvokeExpression( _
New CodeMethodReferenceExpression( _
New CodeVariableReferenceExpression("obj"), _
"MethodA"), _
New CodeMethodInvokeExpression( _
New CodeMethodReferenceExpression( _
New CodeVariableReferenceExpression("obj"), _
"MethodC"), _
New CodeVariableReferenceExpression("j")))))
NOTE: A compiler error will occur when you compile the output code if j or obj aren’t declared and/or initialized. |
This chapter is from Code Generation in Microsoft .NET by Kathleen Dollard (Apress, 2004, ISBN: 1590591372). Check it out at your favorite bookstore today.
Buy this book now. |
Next: Building a CodeDOM Graph >>
More .NET Articles
More By Apress Publishing