使用Roslyn将自定义属性添加到C#类

考虑下面的类在一个文件“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,但是不成功.如何添加自定义属性

解决方法

Syntax.PropertyDeclaration方法一个参数是应用于该属性属性列表.与所有Syntax元素一样,它使用静态SyntaxFactory类中的工厂方法构造.

Roslyn Quoter可以方便地找出如何使用Roslyn生成语法.

在您的具体示例中,重写器的VisitPropertyDeclaration方法应如下所示:

using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
...

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

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

    var newProperty = PropertyDeclaration(
                PredefinedType(
                    Token(SyntaxKind.LongKeyword)),Identifier("Id"))
            .WithModifiers(
                TokenList(
                    Token(SyntaxKind.PublicKeyword)))
            .WithAccessorList(
                AccessorList(
                    List(new AccessorDeclarationSyntax[]{
                        AccessorDeclaration(
                            SyntaxKind.GetAccessorDeclaration)
                        .WithSemicolonToken(
                            Token(SyntaxKind.SemicolonToken)),AccessorDeclaration(
                            SyntaxKind.SetAccessorDeclaration)
                        .WithSemicolonToken(
                            Token(SyntaxKind.SemicolonToken))})))
            .normalizeWhitespace();

    return newProperty;
}

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...