使用自定义属性获取所有字段(包括继承的字段)

时间:2009-12-30 04:37:17

标签: c# reflection attributes

我有一个自定义属性BacksCache,我用它来标记类中的字段,当满足某些条件时需要“默认”。

我正在使用以下代码:

Type type = obj.GetType();
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);

foreach (FieldInfo field in fields)
{
  foreach (Attribute at in field.GetCustomAttributes(true))
  if (at is BacksCache)
  {
    field.SetValue(obj, Utils.DefaultValue(field.FieldType));
  }
}

如果类继承层次结构是扁平的,则此代码可以正常工作。也就是说,如果type是声明所有属性字段的类型,那么一切都很棒。只要我有一个班级A从哪个下级班BB : A)和B有一些属性字段就会崩溃:只有{{1}声明的字段检测到并“默认”。

相关字段为Aprivate,如果这有任何区别。

有关如何解决此问题的任何想法?

3 个答案:

答案 0 :(得分:7)

请注意BindingFlags.FlattenHierarchy选项的小字体:

  

指定public和protected   层次结构中的静态成员应该   被退回私有静态成员   在继承的类中不是   返回即可。静态成员包括   字段,方法,事件和   属性。嵌套类型不是   返回。

粗体短语中的“静态”单词是oops,不返回私有成员。要解决此问题,您需要通过Type.BaseType向上移动继承链。

答案 1 :(得分:2)

你的措辞有点令人困惑,哪个类是基类A或B?您要反映哪一个,基类或派生类。我问,因为我在复制你的问题时遇到了麻烦。我试过这个并且工作正常:

    static void Main(string[] args)
    {

        foreach (var prop in typeof(Sub).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy))
        {
            foreach (var attrib in prop.GetCustomAttributes(typeof(DescriptionAttribute), false))
            {
                Console.WriteLine(prop.Name);
            }
        }

        Console.ReadKey(true);
    }


public class Base
{
    [Description]
    public int IntProp { get; set; }
}

public class Sub : Base
{
    [Description]
    public string StringProp { get; set; }
}

输出正确,它显示两个属性。

此外,我刚刚注意到你正在处理菲尔兹。我这样做了,仍然得到了正确的输出:

    static void Main(string[] args)
    {
        foreach (var prop in typeof(Sub).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy))
        {
            foreach (var attrib in prop.GetCustomAttributes(typeof(DescriptionAttribute), false))
            {
                Console.WriteLine(prop.Name);
            }
        }

        Console.ReadKey(true);
    }


public class Base
{
    [Description]
    public int X;

    [Description]
    public int IntProp { get; set; }
}

public class Sub : Base
{
    [Description]
    public int Y;

    [Description]
    public string StringProp { get; set; }
}

X和Y都输出到控制台。

答案 2 :(得分:0)

Attribute.GetCustomAttributes将搜索继承的值。给出你的例子的代码是:

foreach (Attribute at in Attribute.GetCustomAttributes(field, true))
{
    // Test and set here
}

有关详细说明,请参阅Weitao Su's post on GetCustomAttributes