检索具有特定属性值的属性名称和值。

问题描述 投票:0回答:2

假设有一个属性,如。

public class ValueAttribute : Attribute
{
  public int Val;
  public ValueAttribute(int val)
  {
    Val = val;
  }
}

并将其应用于一个类。

public class Person
{
  [Value(10)]
  public string FirstName;
  [Value(20)]
  public string LastName;
  [Value(30)]
  public string Age;
}

我将如何有效地检索一个 PropertyInfo (最好是没有循环)的属性的第一次出现,该属性具有以下特点 Value(20)?

c# reflection attributes
2个回答
2
投票

首先,你有字段而不是属性,所以如果有什么需要,你需要从一个 FieldInfo 对象。其次,如果没有某种形式的迭代,就没有办法做到你想要的。如果你担心每次都要查找,你可以缓存每个类型的结果。

public static class ValueHelper<T>
{
     private static readonly Dictionary<int, FieldInfo> FieldsByValue;

     static ValueHelper()
     {
         FieldsByValue = typeof(T)
                 .GetFields()
                 .Select(f => new { 
                       Field = f, 
                       Att = f.GetCustomAttribute<ValueAttribute>() 
                  })
                 .Where(c => c.Att != null)
                 .GroupBy(c => c.Att.Val, (val, flds) => new { 
                      Value = val, 
                      Field = flds.First() 
                  })
                 .ToDictionary(c => c.Value, c => c.Field);
     }

     public static FieldInfo GetFieldByValue(int value)
     {
          if (FieldsByValue.TryGetValue(value, out var field)) 
             return field;
          // not found, return null...
          // throw exception, etc
          return null;
     } 

} 

然后可以像这样使用。

var field = ValueHelper<Person>.GetFieldByValue(20);

反射只发生一次(多亏了静态构造函数) 然后被缓存在一个查找表中,以便进一步访问。

如果你 真的 有属性,然后替换为 FieldInfoPropertyInfoGetFieldsGetProperties.

注意:我不确定从反射中返回的字段属性的顺序是否是...。保证. 有可能是按源码顺序返回,但这很可能是一个 实施细节.


0
投票

你可以使用以下代码

var attr = (ValueAttribute)(typeof(Person)
          .GetField("FirstName")
          .GetCustomAttributes(false)
          .GetValue(0));
Console.WriteLine(attr.Val);  
© www.soinside.com 2019 - 2024. All rights reserved.