我有一个类,叫它Book,它的属性叫Name。有了这个属性,我就有了一个与之关联的属性。
public class Book
{
[Author("AuthorName")]
public string Name
{
get; private set;
}
}
在我的主要方法中,我使用反射,并希望获得每个属性的每个属性的键值对。因此,在本例中,我希望看到属性名为“Author”,属性值为“AuthorName”。
问:如何使用反射获取属性上的属性名和值?
只是在找合适的地方放这段代码。
假设你有以下属性:
[Display(Name = "Solar Radiation (Average)", ShortName = "SolarRadiationAvg")]
public int SolarRadiationAvgSensorId { get; set; }
你想要得到ShortName值。你可以:
((DisplayAttribute)(typeof(SensorsModel).GetProperty(SolarRadiationAvgSensorId).GetCustomAttribute(typeof(DisplayAttribute)))).ShortName;
或者泛指:
internal static string GetPropertyAttributeShortName(string propertyName)
{
return ((DisplayAttribute)(typeof(SensorsModel).GetProperty(propertyName).GetCustomAttribute(typeof(DisplayAttribute)))).ShortName;
}
public static class PropertyInfoExtensions
{
public static TValue GetAttributValue<TAttribute, TValue>(this PropertyInfo prop, Func<TAttribute, TValue> value) where TAttribute : Attribute
{
var att = prop.GetCustomAttributes(
typeof(TAttribute), true
).FirstOrDefault() as TAttribute;
if (att != null)
{
return value(att);
}
return default(TValue);
}
}
用法:
//get class properties with attribute [AuthorAttribute]
var props = typeof(Book).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(AuthorAttribute)));
foreach (var prop in props)
{
string value = prop.GetAttributValue((AuthorAttribute a) => a.Name);
}
or:
//get class properties with attribute [AuthorAttribute]
var props = typeof(Book).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(AuthorAttribute)));
IList<string> values = props.Select(prop => prop.GetAttributValue((AuthorAttribute a) => a.Name)).Where(attr => attr != null).ToList();
虽然上面得到最多好评的答案肯定有效,但我建议在某些情况下使用稍微不同的方法。
如果你的类有多个具有相同属性的属性,并且你想要将这些属性排序到字典中,下面是如何做的:
var dict = typeof(Book).GetProperties().ToDictionary(p => p.Name, p => p.GetCustomAttributes(typeof(AuthorName), false).Select(a => (AuthorName)a).FirstOrDefault());
这仍然使用强制转换,但确保强制转换始终有效,因为您将只获得“AuthorName”类型的自定义属性。
如果你有多个以上的属性,答案将得到一个强制转换异常。