Добавление настраиваемых атрибутов в классы C # с помощью Roslyn

Рассмотрим следующий класс в файле "MyClass.cs"

using System;

public class MyClass : Entity<long>
{
    public long Id
    {
        get;
        set;
    }

    [Required]
    public string Name
    {
        get;
        set;
    }

    public string Slug
    {
        get;
        set;
    }

    public DateTime CreatedOn
    {
        get;
        private set;
    }

    public DateTime UpdatedOn
    {
        get;
        private set;
    }

    /* ... */
}

В настоящее время я вручную создаю классы контрактов данных, которые выглядят следующим образом:

[DataContract(Namespace = "http://example.com/", Name = "MyClass")]
public sealed class MyClass
{
    [DataMember(EmitDefaultValue = false, Name = "Id")]
    public long Id
    {
        get;
        set;
    }

    [DataMember(EmitDefaultValue = false, Name = "Name", IsRequired = true)]
    public string Name
    {
        get;
        set;
    }

    [DataMember(EmitDefaultValue = false, Name = "Slug")]
    public string Slug
    {
        get;
        set;
    }

    [DataMember(EmitDefaultValue = false, Name = "CreatedOn")]
    public DateTime CreatedOn
    {
        get;
        set;
    }

    [DataMember(EmitDefaultValue = false, Name = "UpdatedOn")]
    public DateTime UpdatedOn
    {
        get;
        set;
    }
}

Я бы хотел использовать Roslyn для перезаписи " MyClass.cs ", поэтому он выглядит как класс, который я создаю вручную. В настоящее время у меня есть следующее:

using System;
using System.IO;
using Roslyn.Compilers.CSharp;

internal class Program
{
    private static void Main()
    {
        var reader = new StreamReader(@"..\..\MyClass.cs");
        var source = reader.ReadToEnd();
        var tree = SyntaxTree.ParseCompilationUnit(source);
        var rewriter = new MyRewriter();
        var newRoot = rewriter.Visit(tree.Root);
        Console.WriteLine(newRoot.Format());
    }
}

public class MyRewriter : SyntaxRewriter
{
    protected override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
    {
        var declaration = (TypeDeclarationSyntax) base.VisitClassDeclaration(node);

        return ((ClassDeclarationSyntax) declaration).Update(
            declaration.Attributes,
            Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword), Syntax.Token(SyntaxKind.SealedKeyword)),
            declaration.Keyword,
            declaration.Identifier,
            declaration.TypeParameterListOpt,
            null,
            declaration.ConstraintClauses,
            declaration.OpenBraceToken,
            declaration.Members,
            declaration.CloseBraceToken,
            declaration.SemicolonTokenOpt);
    }

    protected override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
    {
        var typeSyntax = node.Type;

        if (node.Identifier.ValueText == "Id")
        {
            typeSyntax = Syntax.IdentifierName("string");
        }

        var newProperty = Syntax.PropertyDeclaration(
            modifiers: Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword)),
            type: typeSyntax,
            identifier: node.Identifier,
            accessorList: Syntax.AccessorList(
                accessors: Syntax.List(
                    Syntax.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, 
                    semicolonTokenOpt: Syntax.Token(SyntaxKind.SemicolonToken)),
                    Syntax.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration,
                    semicolonTokenOpt: Syntax.Token(SyntaxKind.SemicolonToken))
                    )
                )
            );

        return newProperty;
    }
}

Я пытался найти способ добавить настраиваемые атрибуты DataMember и DataContract в MyClass, но безуспешно. Как добавить настраиваемые атрибуты?

12
задан bloudraak 9 February 2012 в 03:08
поделиться