Using Roslyn to parse/transform/generate code: am I aiming too high, or too low?
c#, code-generation, roslyn
Solution
If your requirement is parsing C# source code, then I think Roslyn is a good choice. And if you're going to use it for this part, I think it also makes sense to use it for code generations.
Code generation using Roslyn can be quite verbose (especially when compared with CodeDom), but I think that's not going to be a big issue for you.
I think `SyntaxRewriter` is best suited for making localized changes in code. But you're asking about parsing whole class and generating types based on that, I think for that, querying the syntax tree directly would work best.
For example, the simplest example of generating a read-only interface for all properties in a class could look something like this:
var originalClass =
compilationUnit.DescendantNodes().OfType<ClassDeclarationSyntax>().Single();
string originalClassName = originalClass.Identifier.ValueText;
var properties =
originalClass.DescendantNodes().OfType<PropertyDeclarationSyntax>();
var generatedInterface =
SyntaxFactory.InterfaceDeclaration('I' + originalClassName)
.AddMembers(
properties.Select(
p =>
SyntaxFactory.PropertyDeclaration(p.Type, p.Identifier)
.AddAccessorListAccessors(
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))))
.ToArray());
Problem
(What I'm trying to do is work around the Application.Settings/MVVM problem by generating an interface and wrapper class from the vs-generated settings file.) What I'd like to do is: - Parse a class declaration from file - Generate an interface declaration based on just the (non static) properties of the class - Generate a wrapper class which implements this interface, takes an instance of the original class in the constructor, and 'pipes' all the properties through to the instance. - Generate another class which implements the interface directly. My question is two-fold: - Am I barking up the wrong tree? Would I be better off using Code-Dom, T4, Regex(!) for this, or part of this? (I don't mind a bit of extra work, as this is mostly a learning experience.) - If Roslyn is the way to go, which bit of it should I be looking at? I was kind of naively hoping that there would be some way of walking the tree and spitting out just the bits that I want, but I'm having trouble getting my head round whether/how to use the SyntaxRewriter to do it, or whether to use a fluent-style construction, querying the source multiple times for the bits I need. If you want to comment on the MVVM aspect you can, but that's not the main thrust of the question :)