C# - 通过反射枚举自定义属性

时间:2011-02-26 07:57:15

标签: c#

这是我的属性定义:

[AttributeUsage(AttributeTargets.Field)]
public class Optional : System.Attribute
{
    public Optional()
    {
    }
}

在MyClass中:

[Optional] public TextBox Name;

最后在另一个功能中:

typeof(MyClass).GetFields().ToList<FieldInfo>().ForEach(x => writer.WriteLine(
   x.FieldType + " is called " + 
   x.Name + " and has attributes " + 
   x.GetCustomAttributes(true)[0]
 ));

问题是我收到索引0的错误。我只想检查应用属性的字段。当我删除x.GetCustomAttributes(true)[0]时错误消失。

确切错误:

异常详细信息:System.IndexOutOfRangeException:索引超出了数组的范围。

来源错误:

Line 63:             }
Line 64: 
Line 65:             typeof(T).GetFields().ToList<FieldInfo>().ForEach(x => writer.WriteLine(x.FieldType + " is called " + 
Line 66:                 x.Name + " and has attributes " + 
Line 67:                 x.GetCustomAttributes(true)[0]+ "</br>"));

3 个答案:

答案 0 :(得分:2)

似乎这里可能有两个问题。要查找具有[可选]属性的所有字段,您需要:

typeof(MyClass).GetFields().Where(
   f => f.GetCustomAttributes(typeof(OptionalAttribute), true).Any())

要在所有字段上写出自定义属性,您需要:

typeof(MyClass).ToList<FieldInfo>().ForEach(x => 
{
 writer.WriteLine(
   x.FieldType + " is called " + 
   x.Name + " and has attributes " + 
   string.Join(", ", x.GetCustomAttributes(true).Select(a => a.ToString()).ToArray()));
});

答案 1 :(得分:1)

正如您似乎已经收集到的那样,您收到此错误是因为您正在尝试获取空数组的第0个元素,这当然是非法的。您需要首先过滤掉没有任何属性的字段,如下所示:

var fields = from fieldInfo in typeof(MyClass).GetFields()
             let Attributes = fieldInfo.GetCustomAttributes(true)
             where Attributes.Any()
             select new { fieldInfo.FieldType, fieldInfo.Name, Attributes };

foreach (var field in fields)
{
    writer.WriteLine(field.FieldType + " is called " +
                     field.Name + " and its first attribute is " +
                     field.Attributes.First());
}

如果您对那些OptionalAttribute的人特别感兴趣,那么您可能正在寻找类似的东西:

var fields = from fieldInfo in typeof(MyClass).GetFields()
             let attributes = fieldInfo.GetCustomAttributes(true).OfType<OptionalAttribute>()
             where attributes.Any()
             select new { fieldInfo.FieldType, fieldInfo.Name, Attribute = attributes.Single() };

foreach (var field in fields)
{
    writer.WriteLine(field.FieldType + " is called " +
                     field.Name + " and its OptionalAttribute is " +
                     field.Attribute);
}

答案 2 :(得分:1)

检查属性是否存在:

x.GetCustomAttributes(true).Any(item => item is OptionalAttribute)

我假设您将Optional属性重命名为OptionalAttribute,因为所有属性都应具有“属性”后缀。