获取重写属性的所有属性

时间:2014-02-27 18:49:10

标签: c# reflection custom-attributes

以下面的示例代码为例:

    public class TestMultipleAttributesAttribute : AttributeWithPriority
    {
        public string HelpMessage { get; set; }
    }

    public class Student


    {
        [TestMultipleAttributes(HelpMessage = "Student")]
        public virtual string Name { get; set; }

    }

    public class SpecificStudent : Student
    {
        [TestMultipleAttributes(Priority = 100, HelpMessage = "SpecificStudent")]
        public override string Name { get; set; }
    }

有没有办法通过反思如何为同一覆盖属性获取TestMultipleAttributes的两个实例?

我尝试了以下代码:

   [Test]
    public void testMultipleAttribs()
    {
        var property = typeof(SpecificStudent).GetProperties().FirstOrDefault(x => x.Name == "Name");

        var attribList = property.Attributes; //returns none
        var customAttribs = property.CustomAttributes.ToList(); //returns 1
        var customAttribs2 = property.GetCustomAttributes(inherit: true);// returns 1
        int k = 5;

    }

考虑到的一个解决方案是找到property.DeclaringType,然后重复该过程,并获取它的属性。但是,我发现这不是一种优雅的方式,并且想知道是否有更好的方法。

2 个答案:

答案 0 :(得分:0)

您只有一个名为TestMultipleAttributes的属性,并且您覆盖了它。该属性有多个属性(PriorityHelpMessage),它的工作正常。

您可以创建更多“真实”属性,例如StudentAttributeSpecificStudentAttribute

答案 1 :(得分:0)

我不知道......这是相对优雅的(虽然我确定我至少缺少一个特殊情况)。它应该按照最接近的顺序枚举继承链中的重写或虚拟属性上的所有自定义属性:

public static IEnumerable<Attribute>  AllAttributes( PropertyInfo pi )
{
  if ( pi != null )
  {
    // enumerate all the attributes on this property
    foreach ( object o in pi.GetCustomAttributes( false ) )
    {
      yield return (Attribute) o ;
    }

    PropertyInfo parentProperty = FindNearestAncestorProperty(pi) ;
    foreach( Attribute attr in AllAttributesRecursive(parentProperty) )
    {
      yield return attr ;
    }

  }

}

private static PropertyInfo FindNearestAncestorProperty( PropertyInfo property )
{
  if ( property == null ) throw new ArgumentNullException("property") ;
  if ( property.DeclaringType == null ) throw new InvalidOperationException("all properties must belong to a type");

  // get the property's nearest "ancestor" property
  const BindingFlags flags = BindingFlags.DeclaredOnly
                           | BindingFlags.Public | BindingFlags.NonPublic
                           | BindingFlags.Static | BindingFlags.Instance
                           ;
  Type         t        = property.DeclaringType.BaseType ;
  PropertyInfo ancestor = null ;

  while ( t != null && ancestor == null )
  {
    ancestor = t.GetProperty(property.Name,flags) ;
    t        = t.BaseType ;
  } ;

  return ancestor ;
}