假设有一个属性,如。
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)
?
首先,你有字段而不是属性,所以如果有什么需要,你需要从一个 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);
反射只发生一次(多亏了静态构造函数) 然后被缓存在一个查找表中,以便进一步访问。
如果你 真的 有属性,然后替换为 FieldInfo
与 PropertyInfo
和 GetFields
与 GetProperties
.
注意:我不确定从反射中返回的字段属性的顺序是否是...。保证. 有可能是按源码顺序返回,但这很可能是一个 实施细节.
你可以使用以下代码
var attr = (ValueAttribute)(typeof(Person)
.GetField("FirstName")
.GetCustomAttributes(false)
.GetValue(0));
Console.WriteLine(attr.Val);