I’m going to give a few more basic examples of code generation with Roslyn. The following assume that you have a ClassGenerationSyntax variable named “@class”. The examples have also shortened SyntaxFactory to SF using:
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
Properties
The code
// Add a property
PropertyDeclarationSyntax @property = SF.PropertyDeclaration( SF.ParseTypeName( "String" ), "MyProperty" )
.AddModifiers( SF.Token( SyntaxKind.PublicKeyword ) );
// Add a getter
@property = @property.AddAccessorListAccessors(
SF.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration )
.WithSemicolonToken( SF.Token(SyntaxKind.SemicolonToken )
) );
// Add a private setter
@property = @property.AddAccessorListAccessors(
SF.AccessorDeclaration( SyntaxKind.SetAccessorDeclaration )
.AddModifiers( SF.Token( SyntaxKind.PrivateKeyword ) )
.WithSemicolonToken( SF.Token(SyntaxKind.SemicolonToken )
) );
// Add the property to the class
@class = @class.AddMembers( @property );
Produces the code:
public class MyClass {
public String MyProperty { get; private set; }
}
Variables
This adds a simple field to the class:
FieldDeclarationSyntax aField = SF.FieldDeclaration(
SF.VariableDeclaration(
SF.ParseTypeName( "String" ),
SF.SeparatedList(new [] { SF.VariableDeclarator( SF.Identifier( "_a" ) ) } )
) )
.AddModifiers( SF.Token( SyntaxKind.PrivateKeyword ) );
@class = @class.AddMembers( aField );
Generating the code:
private String _a;
This code initializes the field to a new object:
ExpressionSyntax initializationExpression = SF.ObjectCreationExpression(
SF.Token( SyntaxKind.NewKeyword ),
SF.ParseTypeName( "OtherClass" ),
SF.ArgumentList( SF.SeparatedList<ArgumentSyntax>( new [] {
SF.Argument( SF.LiteralExpression( SyntaxKind.NumericLiteralExpression, SF.Literal( 1 ) ) ),
SF.Argument( SF.LiteralExpression( SyntaxKind.StringLiteralExpression, SF.Literal( "abc" ) ) )
} ) ),
null
);
FieldDeclarationSyntax bField = SF.FieldDeclaration(
SF.VariableDeclaration(
SF.ParseTypeName( "OtherClass" ),
SF.SeparatedList(new [] {
SF.VariableDeclarator(
SF.Identifier( "_b" ),
null,
SF.EqualsValueClause( initializationExpression )
)
} )
) )
.AddModifiers( SF.Token( SyntaxKind.PrivateKeyword ) )
.AddModifiers( SF.Token( SyntaxKind.ReadOnlyKeyword ) )
;
@class = @class.AddMembers( bField );
Generating the code:
private readonly OtherClass _b = new OtherClass(1, "abc");
Field-backed Properties
The following code generates a getter and setter backed by a field:
PropertyDeclarationSyntax property =
SF.PropertyDeclaration( SF.ParseTypeName( "String" ), SF.Identifier( "A" ) )
.AddModifiers( SF.Token( SyntaxKind.PublicKeyword ) )
.AddAccessorListAccessors(
SF.AccessorDeclaration(
SyntaxKind.GetAccessorDeclaration,
SF.Block(
SF.List( new [] {
SF.ReturnStatement( SF.IdentifierName( "_a" ) )
} )
)
),
SF.AccessorDeclaration(
SyntaxKind.SetAccessorDeclaration,
SF.Block(
SF.List( new [] {
SF.ExpressionStatement(
SF.BinaryExpression(
SyntaxKind.SimpleAssignmentExpression,
SF.IdentifierName( "_a" ),
SF.IdentifierName( "value" )
)
)
} )
)
)
)
;
Producing the following code:
public String A {
get {
return _a;
}
set {
_a = value;
}
}
The ratio of code to output shows that it would be a lot easier to generate code from scratch with TextWriter.