Skip to content

Instantly share code, notes, and snippets.

@jagt
Created December 15, 2017 15:16
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jagt/1b77a3c6e2c0ba2aea1ca437997289f2 to your computer and use it in GitHub Desktop.
Save jagt/1b77a3c6e2c0ba2aea1ca437997289f2 to your computer and use it in GitHub Desktop.
Sample roslyn code generation
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editing;
// ref https://msdn.microsoft.com/en-us/magazine/mt707527.aspx
// needed packages
// Microsoft.CSharp;
// Microsoft.CodeAnalysis;
// Microsoft.CodeAnalysis.CSharp;
// Microsoft.CodeAnalysis.CSharp.Workspaces;
// Microsoft.CodeAnalysis.Workspaces;
// Microsoft.CodeAnalysis.Workspaces.Desktop;
/*
using System;
namespace MyTypes
{
public abstract class Person : ICloneable
{
private string _lastName;
private string _firstName;
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = (value);
}
}
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = (value);
}
}
public virtual void Clone()
{
return MemberwiseClone();
}
public Person(string LastName, string FirstName)
{
_lastName = (LastName);
_firstName = (FirstName);
}
}
}
*/
class Program
{
static void Main(string[] args)
{
var workspace = new AdhocWorkspace();
var generator = SyntaxGenerator.GetGenerator(workspace, LanguageNames.CSharp);
var usingDirectives = generator.NamespaceImportDeclaration("System");
var lastNameField = generator.FieldDeclaration("_lastName",
generator.TypeExpression(SpecialType.System_String),
Accessibility.Private);
var firstNameField = generator.FieldDeclaration("_firstName",
generator.TypeExpression(SpecialType.System_String),
Accessibility.Private);
// Generate two properties with explicit get/set
var lastNameProperty = generator.PropertyDeclaration("LastName",
generator.TypeExpression(SpecialType.System_String), Accessibility.Public,
getAccessorStatements: new SyntaxNode[]
{ generator.ReturnStatement(generator.IdentifierName("_lastName")) },
setAccessorStatements: new SyntaxNode[]
{ generator.AssignmentStatement(generator.IdentifierName("_lastName"),
generator.IdentifierName("value"))});
var firstNameProperty = generator.PropertyDeclaration("FirstName",
generator.TypeExpression(SpecialType.System_String),
Accessibility.Public,
getAccessorStatements: new SyntaxNode[]
{ generator.ReturnStatement(generator.IdentifierName("_firstName")) },
setAccessorStatements: new SyntaxNode[]
{ generator.AssignmentStatement(generator.IdentifierName("_firstName"),
generator.IdentifierName("value")) });
// Generate the method body for the Clone method
var cloneMethodBody = generator.ReturnStatement(generator.
InvocationExpression(generator.IdentifierName("MemberwiseClone")));
// Generate a SyntaxNode for the interface's name you want to implement
var ICloneableInterfaceType = generator.IdentifierName("ICloneable");
// Generate the Clone method declaration
var cloneMethoDeclaration = generator.MethodDeclaration("Clone", null,
null, null,
Accessibility.Public,
DeclarationModifiers.Virtual,
new SyntaxNode[] { cloneMethodBody });
// Explicit ICloneable.Clone implemenation
var cloneMethodWithInterfaceType = generator.
AsPublicInterfaceImplementation(cloneMethoDeclaration,
ICloneableInterfaceType);
// Generate parameters for the class' constructor
var constructorParameters = new SyntaxNode[] {
generator.ParameterDeclaration("LastName",
generator.TypeExpression(SpecialType.System_String)),
generator.ParameterDeclaration("FirstName",
generator.TypeExpression(SpecialType.System_String)) };
// Generate the constructor's method body
var constructorBody = new SyntaxNode[] {
generator.AssignmentStatement(generator.IdentifierName("_lastName"),
generator.IdentifierName("LastName")),
generator.AssignmentStatement(generator.IdentifierName("_firstName"),
generator.IdentifierName("FirstName"))};
// Generate the class' constructor
var constructor = generator.ConstructorDeclaration("Person",
constructorParameters, Accessibility.Public,
statements: constructorBody);
// An array of SyntaxNode as the class members
var members = new SyntaxNode[] { lastNameField,
firstNameField, lastNameProperty, firstNameProperty,
cloneMethodWithInterfaceType, constructor };
// Generate the class
var classDefinition = generator.ClassDeclaration(
"Person", typeParameters: null,
accessibility: Accessibility.Public,
modifiers: DeclarationModifiers.Abstract,
baseType: null,
interfaceTypes: new SyntaxNode[] { ICloneableInterfaceType },
members: members);
// Declare a namespace
var namespaceDeclaration = generator.NamespaceDeclaration("MyTypes", classDefinition);
// Get a CompilationUnit (code file) for the generated code
var newNode = generator.CompilationUnit(usingDirectives, namespaceDeclaration).
NormalizeWhitespace();
Console.WriteLine(newNode.ToFullString());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment