C# 如何获取具有指定属性的所有字段的列表?

C# 如何获取具有指定属性的所有字段的列表?,c#,attributes,field,roslyn,C#,Attributes,Field,Roslyn,我正在尝试查找具有指定属性的字段。我试图修改FirstQuickFix示例,因为我认为这可能是一个很好的起点。但是如果我运行代码,什么也不会发生。你知道我的主要问题是什么吗 在阅读了项目概述和演练文档之后,我的理解是,我能够请求在语法树中找到的令牌的属性。语法树是源代码的精确树表示形式。字段的声明与其属性的连接可以通过语义访问。还是我的理解完全错了 [ExportCodeIssueProvider("FirstQuickFix_", LanguageNames.CSharp)] class Co

我正在尝试查找具有指定属性的字段。我试图修改FirstQuickFix示例,因为我认为这可能是一个很好的起点。但是如果我运行代码,什么也不会发生。你知道我的主要问题是什么吗

在阅读了项目概述和演练文档之后,我的理解是,我能够请求在语法树中找到的令牌的属性。语法树是源代码的精确树表示形式。字段的声明与其属性的连接可以通过语义访问。还是我的理解完全错了

[ExportCodeIssueProvider("FirstQuickFix_", LanguageNames.CSharp)]
class CodeIssueProvider : ICodeIssueProvider
{
    public IEnumerable<CodeIssue> GetIssues
      (IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
    {
        var tokens = from nodeOrToken in node.ChildNodesAndTokens()
                     where nodeOrToken.HasAnnotations(Type.GetType("myAttribute"))
                     select nodeOrToken.AsToken();

        foreach (var token in tokens)
        {
            var issueDescription = string.Format("found!!!");
            yield return new CodeIssue(CodeIssueKind.Info, token.Span, issueDescription);
        }
    }
}

下面是一个工作代码示例,用于迭代类中具有自定义属性的属性。 您可以将此作为“如何获取具有指定属性的所有字段的列表”的提示


为此,可以使用LINQ获取具有指定名称的所有
AttributeSyntax
节点,然后使用
Parent
(两次)获取表示字段的节点:

var fields = root.DescendantNodes()
                 .OfType<AttributeSyntax>()
                 .Where(a => a.Name.ToString() == "myAttribute")
                 .Select(a => a.Parent.Parent)
                 .Cast<FieldDeclarationSyntax>();
var fields=root.degenantNodes()
第()类
.Where(a=>a.Name.ToString()==“myAttribute”)
.Select(a=>a.Parent.Parent)
.Cast();
这是最原始的版本,仅在语法级别上有效,因此,如果在另一个命名空间中有同名的属性,使用属性的全名(包括命名空间),或者使用
using
使用别名引用属性类型,则此版本将无法正常工作


如果要支持该功能,需要获取语义模型,然后获取表示属性类型的符号。

对于您提供的已编辑示例,可以将LINQ查询与type.GetField方法结合使用:

using System.Collections.Generic;
using System.Linq;

class TestAttribute : System.Attribute { }

class State
{
    [Test] string name;
    [Test] string address;
    [Test] public string name2;
    [Test] public string address2;
    float height;
    public State(string name_, string address_, float height_)
    {
        name = name_;
        address = address_;
        height = height_;
        name2 = name_ + "2";
        address2 = address_ + "2";
    }
}

public class Program
{
    static void ShowFields<T>(IEnumerable<T> fieldList)
    {
        foreach (var field in fieldList)
        {
            System.Console.WriteLine(field.ToString());
        }
    }

    public static void Main(string[] args)
    {            
        State s = new State("Bob", "221 B Baker Street", 5.4f);
        System.Type stateType = typeof(State);
        System.Reflection.FieldInfo[] publicFieldList = stateType.GetFields();
        System.Console.WriteLine("----all public fields----");
        ShowFields(publicFieldList);

        System.Console.WriteLine("----all non public or instance fields----");
        System.Reflection.FieldInfo[] nonPublicFieldList;
        nonPublicFieldList = stateType.GetFields(System.Reflection.BindingFlags.NonPublic| System.Reflection.BindingFlags.Instance);
        ShowFields(nonPublicFieldList);

        var customAttributeFieldList = from t in stateType.GetFields()
        where t.GetCustomAttributes(false).Any(a => a is TestAttribute)
        select t;
        System.Console.WriteLine("----only public fields marked with a particular custom attribute----");
        ShowFields(customAttributeFieldList);
    }
}
使用System.Collections.Generic;
使用System.Linq;
类TestAttribute:System.Attribute{}
阶级国家
{
[测试]字符串名称;
[测试]字符串地址;
[测试]公共字符串名称2;
[测试]公共字符串地址2;
浮动高度;
公共状态(字符串名称、字符串地址、浮动高度)
{
名称=名称;
地址=地址;
高度=高度;
名称2=名称+2;
地址2=地址+2;
}
}
公共课程
{
静态无效显示字段(IEnumerable fieldList)
{
foreach(字段列表中的变量字段)
{
System.Console.WriteLine(field.ToString());
}
}
公共静态void Main(字符串[]args)
{            
州s=新州(“鲍勃”,“贝克街221号B”,5.4f);
System.Type stateType=typeof(状态);
System.Reflection.FieldInfo[]publicFieldList=stateType.GetFields();
System.Console.WriteLine(“----所有公共字段----”;
展示区(publicFieldList);
System.Console.WriteLine(“----所有非公共或实例字段----”;
System.Reflection.FieldInfo[]非公开字段列表;
nonPublicFieldList=stateType.GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
显示字段(非公开字段列表);
var customAttributeFieldList=来自stateType.GetFields()中的t
其中t.GetCustomAttributes(false).Any(a=>a是TestAttribute)
选择t;
System.Console.WriteLine(----仅用特定自定义属性标记的公共字段----);
显示字段(customAttributeFieldList);
}
}

我认为您混淆了注释和属性。注释是Roslyn的一项功能,可用于标记语法树中的某些节点。它们与属性无关。@svick谢谢这是一个很好的提示,但是我如何访问或查找具有指定属性的所有字段?我将添加一个例子,我试图找到我的问题。但我有点困惑,有可能在我的代码中集成这个例子吗?我的mayjor问题是,我以前从未与attributes和roslyn合作过。如何在Roslyn中获取该类的n个实例?我必须通过文档或节点进行操作吗?我想实现我想要的真的很容易,但是我没有得到,对不起@安东:我不确定你的背景,我也不熟悉罗斯林。我试图回答你问题的第二部分“我想要实现的是找到ie.所有属性为myAttribute的字段:@jacobaloysious除了类型不是来自已编译程序集之外,它来自Roslyn语法树。你不能用反射来做这些。@svick:我不确定Roslyn的数据结构/对象。我想举一个例子来获取属性的自定义属性,仅此而已。@jacobaloyous我的观点是,这不是问题的重点,所以你的答案在这里是无用的。谢谢@svick,到目前为止这应该足够了,但我只得到了整个字符串
privat int myField=0超出
字段
变量。。。我没有看到任何可以帮助我的对象方法或属性。但我相信一定有机会获得这些信息。还是我必须走语义的道路?因为我只需要字段名。。。当然,有不同的快速和肮脏的解决方案来获取字段名,但我更喜欢一个好的解决方案。谢谢@Anton您在该变量中没有得到
字符串
,而是得到了
FieldDeclarationSyntax
es的集合,这正是您需要的信息。非常感谢!我试图用foreach循环访问集合的条目,但没有给变量指定特定类型,只是使用了var,因此visual studio没有给我这个FieldDeclarationSyntax的正确属性和方法;-)
var fields = root.DescendantNodes()
                 .OfType<AttributeSyntax>()
                 .Where(a => a.Name.ToString() == "myAttribute")
                 .Select(a => a.Parent.Parent)
                 .Cast<FieldDeclarationSyntax>();
using System.Collections.Generic;
using System.Linq;

class TestAttribute : System.Attribute { }

class State
{
    [Test] string name;
    [Test] string address;
    [Test] public string name2;
    [Test] public string address2;
    float height;
    public State(string name_, string address_, float height_)
    {
        name = name_;
        address = address_;
        height = height_;
        name2 = name_ + "2";
        address2 = address_ + "2";
    }
}

public class Program
{
    static void ShowFields<T>(IEnumerable<T> fieldList)
    {
        foreach (var field in fieldList)
        {
            System.Console.WriteLine(field.ToString());
        }
    }

    public static void Main(string[] args)
    {            
        State s = new State("Bob", "221 B Baker Street", 5.4f);
        System.Type stateType = typeof(State);
        System.Reflection.FieldInfo[] publicFieldList = stateType.GetFields();
        System.Console.WriteLine("----all public fields----");
        ShowFields(publicFieldList);

        System.Console.WriteLine("----all non public or instance fields----");
        System.Reflection.FieldInfo[] nonPublicFieldList;
        nonPublicFieldList = stateType.GetFields(System.Reflection.BindingFlags.NonPublic| System.Reflection.BindingFlags.Instance);
        ShowFields(nonPublicFieldList);

        var customAttributeFieldList = from t in stateType.GetFields()
        where t.GetCustomAttributes(false).Any(a => a is TestAttribute)
        select t;
        System.Console.WriteLine("----only public fields marked with a particular custom attribute----");
        ShowFields(customAttributeFieldList);
    }
}