Reputation: 2761
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)
?
Upvotes: 0
Views: 166
Reputation: 12799
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.
Upvotes: 2
Reputation: 863
You could use below code
var attr = (ValueAttribute)(typeof(Person)
.GetField("FirstName")
.GetCustomAttributes(false)
.GetValue(0));
Console.WriteLine(attr.Val);
Upvotes: 0