6

指定された属性を持つフィールドを見つけようとしています。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);
        }
    }
}

編集:

私が達成したいのは、すなわちを見つけることです。属性myAttributeを持つすべてのフィールド:

namespace ConsoleApplication
{
    class Program
    {
        [myAttribute]
        string myField = "test";

        public void testing()
        {
            Console.WriteLine(myField);
        }
    }
}
4

3 に答える 3

7

これを行うには、LINQを使用AttributeSyntaxして指定した名前のすべてのノードを取得しParentてから、(2回)を使用してフィールドを表すノードを取得します。

var fields = root.DescendantNodes()
                 .OfType<AttributeSyntax>()
                 .Where(a => a.Name.ToString() == "myAttribute")
                 .Select(a => a.Parent.Parent)
                 .Cast<FieldDeclarationSyntax>();

これは最も原始的なバージョンであり、構文レベルでのみ機能するため、別の名前空間に同じ名前の属性がある場合、属性のフルネーム(名前空間を含む)を使用usingする場合、またはエイリアスを使用して属性タイプを参照します。

これをサポートする場合は、セマンティックモデルを取得してから、属性のタイプを表すシンボルを取得する必要があります。

于 2013-03-16T19:33:31.357 に答える
0

提供する編集済みの例では、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);
    }
}
于 2017-09-30T21:52:02.573 に答える
-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; }
}
于 2013-03-15T03:21:06.983 に答える