简体   繁体   中英

Retrieve name and value of property has a specific attribute value

Assume there is an attribute such as:

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

And it is applied to a class:

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

How would I go about efficiently retrieving a PropertyInfo (preferably without loop/iteration) of the first occurrence of a property that has Value(20) ?

First of all, you have fields and not properties, so if anything you'd need to get the attributes from a FieldInfo object. Second, there is no way to do what you want without some form of iteration. If you are worried about having to look it up each time you could cache the results per type.

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;
     } 

} 

This can then be used like:

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

The reflection only occurs once (thanks to the static constructor) and then is cached in a lookup table for further accesses.

If you really have properties, then replace FieldInfo with PropertyInfo and GetFields with GetProperties .

Note: I am not sure if the order of fields/properties returned from reflection is guaranteed . It may be the case that they are returned in source order, but that may very well be an implementation detail .

You could use below code

var attr = (ValueAttribute)(typeof(Person)
          .GetField("FirstName")
          .GetCustomAttributes(false)
          .GetValue(0));
Console.WriteLine(attr.Val);  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM