C# 如何使用Roslyn生成类字段的初始化

C# 如何使用Roslyn生成类字段的初始化,c#,roslyn,C#,Roslyn,我知道如何在方法内部创建局部变量,例如: LocalDeclarationStatement(VariableDeclaration(IdentifierName("MyClass")) .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("nameOfvariable")) .WithInitializer( Equ

我知道如何在方法内部创建局部变量,例如:

LocalDeclarationStatement(VariableDeclaration(IdentifierName("MyClass"))
            .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("nameOfvariable"))
                .WithInitializer(
                    EqualsValueClause(
                        ObjectCreationExpression(IdentifierName("MyClass")).WithArgumentList(arguments)
                            .WithNewKeyword(Token(SyntaxKind.NewKeyword)))))));
你能给我:

MyClass nameOfvariable = new MyClass();
但假设我已经创建了一个字段,现在我只想初始化它(在方法、构造函数或任何东西中),如下所示:

nameOfVariable = new MyClass();
internal static void Execute()
{
    const string source = @"
using System;

class MyClass
{
    void Method()
    {
        MyClass nameOfVariable, another;
    }
}
";
    var tree = CSharpSyntaxTree.ParseText(source);
    var compilation = CSharpCompilation.Create("MyCompilation", new[] { tree }, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) });
    var semanticModel = compilation.GetSemanticModel(tree);
    var root = tree.GetRoot();

    var local = root.DescendantNodes().OfType<LocalDeclarationStatementSyntax>().First();
    var method = local.Ancestors().OfType<MethodDeclarationSyntax>().First();

    var variableIdentifier = SyntaxFactory.IdentifierName("nameOfVariable");
    var classIdentifier = SyntaxFactory.IdentifierName("MyClass");
    var objectCreationExpression = SyntaxFactory.ObjectCreationExpression(classIdentifier, SyntaxFactory.ArgumentList(), null);
    var assignment = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, variableIdentifier, objectCreationExpression);
    var expressionStatement = SyntaxFactory.ExpressionStatement(assignment).WithAdditionalAnnotations(Formatter.Annotation);
    var newMethod = method.AddBodyStatements(expressionStatement);

    var newRoot = root.ReplaceNode(method.Body, newMethod.Body);
    var formattedRoot = Formatter.Format(newRoot, Formatter.Annotation, new AdhocWorkspace());

    Console.WriteLine(formattedRoot.GetText());
    Console.Read();
}
我该怎么做?我猜这和VariableDeclerator有关,但我找不到正确的方法,所以我可以将它添加到包含语句语法的列表中。我也可以将VariableDeclaration更改为“VariableDeclaration(IdentifierName(“”)”),但这在语句前面给了我一个难看的额外空间

我似乎在为Roslyn的一些非常基本的东西而挣扎,我试着去检查,但这感觉像是一种强迫的方式(感觉它创建了比需要多得多的代码)

更新:应该澄清我知道如何创建方法/构造函数。当我只能访问字段名和字段类型时,我只是在寻找一种初始化字段的方法。因此,我只想生成以下代码:

myField = new MyField();

你就快到了,你只需要创造一切。这应该可以满足您的兴趣:

const string source = @"
using System;

class MyClass
{
    void Method()
    {
        MyClass nameOfVariable;
    }
}
";
var tree = CSharpSyntaxTree.ParseText(source);
var compilation = CSharpCompilation.Create("MyCompilation", new[] { tree }, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) });
var semanticModel = compilation.GetSemanticModel(tree);
var root = tree.GetRoot();

var local = root.DescendantNodes().OfType<LocalDeclarationStatementSyntax>().First();
var declaration = local.Declaration;
var declarator = declaration.Variables.First();

var identifier = SyntaxFactory.IdentifierName("MyClass");
var objectCreationExpression = SyntaxFactory.ObjectCreationExpression(identifier, SyntaxFactory.ArgumentList(), null);
var equalsValueClause = SyntaxFactory.EqualsValueClause(objectCreationExpression);
var newDeclarator = declarator.WithInitializer(equalsValueClause).WithAdditionalAnnotations(Formatter.Annotation);
var newRoot = root.ReplaceNode(declarator, newDeclarator);
var formattedRoot = Formatter.Format(newRoot, Formatter.Annotation, new AdhocWorkspace());

Console.WriteLine(formattedRoot.GetText());
Console.Read();
结果:


经过更多的尝试和寻找,我找到了答案。有一种叫做“AssignmentExpression”的东西可以使用

下面是一个如何使用它的示例:

ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName("myField"),
            ObjectCreationExpression(IdentifierName("MyClass")).WithArgumentList(arguments)
                .WithNewKeyword(Token(SyntaxKind.NewKeyword))));
这将给你:

myField = new Myclass(); 
因此,现在很容易将创建和赋值/初始化分离到两个不同的语句

请注意,我使用的是“使用静态Microsoft.CodeAnalysis.CSharp.SyntaxFactory”,因此我不必一直编写SyntaxFactory。

或者您可以转到“”,将代码粘贴到小文本框中,然后单击“获取Roslyn API调用以生成此代码”

(我可以生成你上面发布的代码,但是有点长。所以我用一个简单的例子

例如,假设您粘贴“DateTime mydate2=new DateTime()”,该工具将生成以下代码:-

LocalDeclarationStatement(
VariableDeclaration(
    IdentifierName("DateTime"))
.WithVariables(
    SingletonSeparatedList<VariableDeclaratorSyntax>(
        VariableDeclarator(
            Identifier("mydate2"))
        .WithInitializer(
            EqualsValueClause(
                ObjectCreationExpression(
                    IdentifierName("DateTime"))
                .WithArgumentList(
                    ArgumentList())))))).WithSemicolonToken(
MissingToken(SyntaxKind.SemicolonToken)).NormalizeWhitespace()
LocalDeclarationStatement(
可变声明(
标识符名称(“日期时间”))
.带变量(
单音分隔列表(
变量声明器(
标识符(“mydate2”))
.使用初始值设定项(
等值条款(
ObjectCreationExpression(
标识符名称(“日期时间”))
.WithArgumentList(
ArgumentList()(
MissingToken(SyntaxKind.SemicolonToken)).NormalizeWhitespace()
然后,您只需使用SyntaxFactory修复代码,例如:-

   var myDeclaratyion = SyntaxFactory.LocalDeclarationStatement(
SyntaxFactory.VariableDeclaration(
    SyntaxFactory.IdentifierName("DateTime")).
WithVariables(
    SyntaxFactory.SingletonSeparatedList<VariableDeclaratorSyntax>(
        SyntaxFactory.VariableDeclarator(
            SyntaxFactory.Identifier("mydate2")).
        WithInitializer(
            SyntaxFactory.EqualsValueClause(
                SyntaxFactory.ObjectCreationExpression(
                    SyntaxFactory.IdentifierName("DateTime"))
                .WithArgumentList(
                    SyntaxFactory.ArgumentList())))))).WithSemicolonToken(SyntaxFactory.MissingToken(SyntaxKind.SemicolonToken)).NormalizeWhitespace();
var myDeclarationion=SyntaxFactory.LocalDeclarationStatement(
SyntaxFactory.VariableDeclaration(
SyntaxFactory.IdentifierName(“日期时间”)。
带变量(
SyntaxFactory.SingletonSeparatedList(
SyntaxFactory.VariableDeclarator(
标识符(“mydate2”))。
带初始值设定项(
SyntaxFactory.EqualsValueClause(
SyntaxFactory.ObjectCreationExpression(
SyntaxFactory.IdentifierName(“日期时间”))
.WithArgumentList(
SyntaxFactory.ArgumentList();

谢谢你的回答,但这并不是我想要的。我可能应该更新我的标题,因为我在创建方法/类方面没有任何问题。问题是我以前创建了所有内容,现在我只想初始化字段(“nameOfVariable=new MyClass”)我唯一可以访问的是变量名+类型。您的示例代码与我的示例代码基本相同(但顺序不同)。问题是什么?您说要初始化字段,这正是它所做的。是的,但您正在创建对象并在同一行上初始化它(与我的示例代码相同)。问题是我想创建对象并在另一行/位置对其进行初始化。哦,好的。所以您需要两条语句:
MyClass nameOfVariable;
nameOfVariable=new MyClass()
?没错,但现在找到了一种方法。发布了我自己使用“AssignmentExpression”的答案这似乎很有效。但还是谢谢你的帮助!酷。谢谢你的提及。我不知道。尽管你有些保留意见,但它看起来是一个非常有用的工具。