使用roslyn获取属性参数

Flo*_*ian 4 .net c# roslyn

我尝试MyAttribute用Roslyn 获取命名参数.

var sourceCode = (@"
    public class MyAttribute : Attribute
    {
        public string Test { get; set; }
    }

    [MyAttribute(Test = ""Hello"")]
    public class MyClass { }
");

var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var compilation = CSharpCompilation.Create("MyCompilation", new[] { syntaxTree }, new[] { mscorlib });
var semanticModel = compilation.GetSemanticModel(syntaxTree);

var syntaxRoot = syntaxTree.GetRoot();
var classNode = syntaxRoot.DescendantNodes().OfType<ClassDeclarationSyntax>().Skip(1).First();
var classModel = (ITypeSymbol)semanticModel.GetDeclaredSymbol(classNode);
var firstAttribute = classModel.GetAttributes().First();
Run Code Online (Sandbox Code Playgroud)

但是firstAttribute.AttributeClass.Kind等于ErrorType并且因此不firstAttribute.NamedArguments包含任何元素.

代码不是anlyzer或者我有更完整的上下文,比如解决方案.

我看不出roslyn缺少任何引用或其他内容.我该怎么做才能完全分析属性?

Evk*_*Evk 6

您需要完全限定Attribute类型名称:

var sourceCode = (@"
    public class MyAttribute : System.Attribute // < here
    {
        public string Test { get; set; }
    }

    [MyAttribute(Test = ""Hello"")]
    public class MyClass { }
");
Run Code Online (Sandbox Code Playgroud)

然后它将按预期工作:

var firstNamedArg = firstAttribute.NamedArguments[0];
var key = firstNamedArg.Key; // "Test"
var value = firstNamedArg.Value.Value; // "Hello"
Run Code Online (Sandbox Code Playgroud)

或者,您可以using System;在顶部添加:

var sourceCode = (@"
    using System;
    public class MyAttribute : Attribute
    {
        public string Test { get; set; }
    }

    [MyAttribute(Test = ""Hello"")]
    public class MyClass { }
");
Run Code Online (Sandbox Code Playgroud)


Ray*_*ega 5

SemanticModel您还可以简单地使用语法 API 来获取属性的参数信息,而不是使用 Roslyn :

        var firstAttribute = classNode.AttributeLists.First().Attributes.First();
        var attributeName = firstAttribute.Name.NormalizeWhitespace().ToFullString();
        Console.WriteLine(attributeName);
        // prints --> "MyAttribute"

        var firstArgument = firstAttribute.ArgumentList.Arguments.First();

        var argumentFullString = firstArgument.NormalizeWhitespace().ToFullString();
        Console.WriteLine(argumentFullString);
        // prints --> Test = "Hello"

        var argumentName = firstArgument.NameEquals.Name.Identifier.ValueText;
        Console.WriteLine(argumentName);
        // prints --> Test

        var argumentExpression = firstArgument.Expression.NormalizeWhitespace().ToFullString();
        Console.WriteLine(argumentExpression);
        // prints --> "Hello"
Run Code Online (Sandbox Code Playgroud)