【问题标题】:C# Reflection : Finding Custom Attributes on a Class PropertyC# 反射:在类属性上查找自定义属性
【发布时间】:2014-03-30 13:36:25
【问题描述】:

我想为类的特定属性定义一个自定义属性。基于反射,应该可以检查属性是否使用此属性注释。第一个 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

【问题讨论】:

    标签: c# reflection custom-attributes


    【解决方案1】:

    您需要使用GetProperties 而不是GetFields,因为TestClass 中没有任何字段,您有两个自动实现 属性。而BindingFlags.NonPublic 标志似乎没有必要,因为您的属性定义为public

    var infos = typeof(TestClass)
                .GetProperties(BindingFlags.Public | 
                               BindingFlags.Instance);
    

    【讨论】:

    • OP 确实TestClass 中有字段 - 否则断言将失败。它们是编译器生成的,但它们肯定存在。但它们没有这些属性。
    • @JonSkeet 你说得对,但没有办法通过反射获得它们,对吧?
    • 不,这不是真的。 OP 已经得到它们 - 因此第一个断言有效。 (有一个断言有两个字段。)这只是属性应用于什么的问题。
    【解决方案2】:

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

    [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();
    

    (你可能要考虑你是否真的要拿起非公共财产。)

    【讨论】:

      猜你喜欢
      • 2017-05-31
      • 1970-01-01
      • 1970-01-01
      • 2010-10-22
      • 1970-01-01
      • 1970-01-01
      • 2011-03-28
      • 2017-04-24
      相关资源
      最近更新 更多