C#反射:在类属性上查找自定义属性

时间:2014-03-30 13:36:26

标签: c# reflection custom-attributes

我想为类的特定属性定义自定义属性。基于反射,应该可以检查属性是否使用此属性进行注释。第一个Assert.AreEqual(2,infos.Length)通过但第二个Assert.AreEqual(1,properties.Count)失败,其中properties.Count = 0.我缺少什么?

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Reflection;

namespace Test.UnitTesting.Rest.ParameteterModels
{
    public class IncludableAttribute : Attribute
    {
    }

    public class TestClass
    {
        [Includable]
        public List<string> List1 { get; set; }

        public List<string> List2 { get; set; }

        public TestClass()
        {

        }
    }


    [TestClass]
    public class IncludeParamaterModelTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            List<string> properties = new List<string>();

            FieldInfo[] infos = typeof(TestClass).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            Assert.AreEqual(2, infos.Length);

            foreach (FieldInfo fi in infos)
            {
                if (fi.IsDefined(typeof(IncludableAttribute), true)) properties.Add(fi.Name);
            }
            Assert.AreEqual(1, properties.Count);
        }
    }
}

此问题与C# Reflection : Finding Attributes on a Member Field

类似

2 个答案:

答案 0 :(得分:2)

您需要使用GetProperties代替GetFields,因为TestClass中没有任何字段,您有两个自动实现的属性。{ {1}}标记似乎不必要,因为您的属性定义为BindingFlags.NonPublic

public

答案 1 :(得分:1)

您的属性正在应用于属性。虽然您有字段,但它们是由编译器创建的 - 并且您的自定义属性未应用于它们。您的代码大致相当于:

[CompilerGenerated]
private List<string> list1;

[Includable]
public List<string> List1 { get { return list1; } set { list1 = value; } }

[CompilerGenerated]
private List<string> list2;
public List<string> List2 { get { return list2; } set { list2 = value; } }

正如您所看到的,仍有两个字段(list1list2) - 这就是您的第一个断言成功的原因。但是,这些都没有Includable属性。它是List1 属性

所以你需要要求的是属性而不是字段。我也是用LINQ做的,而不是明确地循环:

var properties = typeof(TestClass)
                     .GetProperties(BindingFlags.NonPublic | 
                                    BindingFlags.Public | 
                                    BindingFlags.Instance)
                     .Where(p => p.IsDefined(typeof(IncludableAttribute), true)
                     .ToList();

(您可能需要考虑是否真的想要获取非公共属性。)