我正在尝试查找具有指定属性的字段。我试图修改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);
}
}
}
编辑:
我想要实现的目标是找到ie。具有属性myAttribute的所有字段:
namespace ConsoleApplication
{
class Program
{
[myAttribute]
string myField = "test";
public void testing()
{
Console.WriteLine(myField);
}
}
}
答案 0 :(得分:6)
为此,您可以使用LINQ获取具有指定名称的所有AttributeSyntax
个节点,然后使用Parent
(两次)来获取表示该字段的节点:
var fields = root.DescendantNodes()
.OfType<AttributeSyntax>()
.Where(a => a.Name.ToString() == "myAttribute")
.Select(a => a.Parent.Parent)
.Cast<FieldDeclarationSyntax>();
这是最原始的版本,仅适用于语法级别,因此如果在另一个命名空间中具有相同名称的属性,则使用该属性的全名(包括命名空间)或者您使用using
使用别名来引用属性类型。
如果你想支持它,你需要获得语义模型,然后获得表示属性类型的符号。
答案 1 :(得分:1)
对于您提供的已编辑示例,您可以将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);
}
}
答案 2 :(得分:-3)
这是工作代码示例,用于在类中使用自定义属性迭代属性。 您可以使用此提示“如何获取具有指定属性的所有字段的列表?”。
class Program
{
static void Main(string[] args)
{
MyClass myClass = new MyClass();
var type = myClass.GetType();
foreach (var property in type.GetProperties())
{
//Get ALL custom attributes of the property
var propattr = property.GetCustomAttributes(false);
//Get MyAttribute Attribute of the Property
object attr =
(from row in propattr
where row.GetType() == typeof(MyAttribute)
select row).FirstOrDefault();
if (attr == null || !(attr is MyAttribute))
continue;
var myAttribute = attr as MyAttribute;
//output: NameAttrValue and AgeAttrValue
Console.WriteLine(myAttribute.Val);
//Output: Name and Age
Console.WriteLine(property.Name);
}
}
}
public class MyClass
{
[My("NameAttrValue")]
public string Name { get; set; }
[My("AgeAttrValue")]
public int Age { get; set; }
public MyClass()
{
this.Name = "Jac";
this.Age = 27;
}
}
public class MyAttribute : Attribute
{
public MyAttribute(string val)
{
this.Val = val;
}
public string Val { get; set; }
}