(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:
My question is two-fold:
If you want to comment on the MVVM aspect you can, but that's not the main thrust of the question :)
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());
On the question of code generation, my advice is to actually use a combination of inline code snippets (parsed using CSharpSyntaxTree.ParseText) and manually generated SyntaxNodes, but with a strong preference for the former.  I have also used T4 in the past but am moving away from them due to general lack of integration & capability.
SyntaxNodes if majority is procedural.SyntaxFactory API provides guidance on valid syntax.CSharpParseOptions.Default.WithKind(SourceCodeKind.Script) to get the right syntax nodes back.GlobalStatementSyntax and then access the Statement property as a BlockSyntax.Use a helper method to parse single SyntaxNodes: 
    private static TSyntax ParseText<TSyntax>(string code, bool asScript = false)
    {
        var options = asScript
            ? CSharpParseOptions.Default.WithKind(SourceCodeKind.Script)
            : CSharpParseOptions.Default;
        var syntaxNodes =
            CSharpSyntaxTree.ParseText(code, options)
                .GetRoot()
                .ChildNodes();
        return syntaxNodes.OfType<TSyntax>().First();
    }
SyntaxNodes by hand you will typically want to make a final call to SyntaxTree.NormalizeWhitespace(elasticTrivia: true) to make the code "round-trippable".SyntaxNode.ToFullString() to get the actual code text including trivia.SyntaxTree.WithFilePath() as a convenient place to store the eventual file name for when you come to write out the code.CompilationUnitSyntaxs.Formatter.Format as one of the final steps.I think Roslyn is a great way to solve this problem.  In terms of what part of Roslyn would I use - I would probably use a SyntaxWalker over the original class, and then use the Fluent API to build up new SyntaxNodes for the new types you want to generate.  You may be able to re-use some parts of the original tree in the generated code (for example, the argument lists, etc).
A quick example of what this might look like is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
using Roslyn.Services;
using Roslyn.Services.CSharp;
    class Program
    {
        static void Main(string[] args)
        {
            var syntaxTree = SyntaxTree.ParseText(@"
class C
{
    internal void M(string s, int i)
    {
    }
}");
        }
    }
class Walker : SyntaxWalker
{
    private InterfaceDeclarationSyntax @interface = Syntax.InterfaceDeclaration("ISettings");
    private ClassDeclarationSyntax wrapperClass = Syntax.ClassDeclaration("SettingsWrapper")
        .WithBaseList(Syntax.BaseList(
            Syntax.SeparatedList<TypeSyntax>(Syntax.ParseTypeName("ISettings"))));
    private ClassDeclarationSyntax @class = Syntax.ClassDeclaration("SettingsClass")
        .WithBaseList(Syntax.BaseList(
            Syntax.SeparatedList<TypeSyntax>(Syntax.ParseTypeName("ISettings"))));
    public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
        var parameters = node.ParameterList.Parameters.ToArray();
        var typeParameters = node.TypeParameterList.Parameters.ToArray();
        @interface = @interface.AddMembers(
            Syntax.MethodDeclaration(node.ReturnType, node.Identifier.ToString())
                .AddParameterListParameters(parameters)
                .AddTypeParameterListParameters(typeParameters));
        // More code to add members to the classes too.
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With