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.