我有一个类,叫它Book,它的属性叫Name。有了这个属性,我就有了一个与之关联的属性。
public class Book
{
[Author("AuthorName")]
public string Name
{
get; private set;
}
}
在我的主要方法中,我使用反射,并希望获得每个属性的每个属性的键值对。因此,在本例中,我希望看到属性名为“Author”,属性值为“AuthorName”。
问:如何使用反射获取属性上的属性名和值?
虽然上面得到最多好评的答案肯定有效,但我建议在某些情况下使用稍微不同的方法。
如果你的类有多个具有相同属性的属性,并且你想要将这些属性排序到字典中,下面是如何做的:
var dict = typeof(Book).GetProperties().ToDictionary(p => p.Name, p => p.GetCustomAttributes(typeof(AuthorName), false).Select(a => (AuthorName)a).FirstOrDefault());
这仍然使用强制转换,但确保强制转换始终有效,因为您将只获得“AuthorName”类型的自定义属性。
如果你有多个以上的属性,答案将得到一个强制转换异常。
使用typeof(Book). getproperties()获取PropertyInfo实例数组。然后对每个PropertyInfo使用GetCustomAttributes()来查看它们中是否有Author Attribute类型。如果有,您可以从属性信息中获得属性的名称,并从属性中获得属性值。
沿着这些行来扫描类型中具有特定属性类型的属性,并在字典中返回数据(注意,通过将类型传递到例程中,这可以变得更加动态):
public static Dictionary<string, string> GetAuthors()
{
Dictionary<string, string> _dict = new Dictionary<string, string>();
PropertyInfo[] props = typeof(Book).GetProperties();
foreach (PropertyInfo prop in props)
{
object[] attrs = prop.GetCustomAttributes(true);
foreach (object attr in attrs)
{
AuthorAttribute authAttr = attr as AuthorAttribute;
if (authAttr != null)
{
string propName = prop.Name;
string auth = authAttr.Name;
_dict.Add(propName, auth);
}
}
}
return _dict;
}
如果你的意思是“对于带有一个参数的属性,列出属性名称和参数值”,那么在。net 4.5中通过CustomAttributeData API会更容易:
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
public static class Program
{
static void Main()
{
PropertyInfo prop = typeof(Foo).GetProperty("Bar");
var vals = GetPropertyAttributes(prop);
// has: DisplayName = "abc", Browsable = false
}
public static Dictionary<string, object> GetPropertyAttributes(PropertyInfo property)
{
Dictionary<string, object> attribs = new Dictionary<string, object>();
// look for attributes that takes one constructor argument
foreach (CustomAttributeData attribData in property.GetCustomAttributesData())
{
if(attribData.ConstructorArguments.Count == 1)
{
string typeName = attribData.Constructor.DeclaringType.Name;
if (typeName.EndsWith("Attribute")) typeName = typeName.Substring(0, typeName.Length - 9);
attribs[typeName] = attribData.ConstructorArguments[0].Value;
}
}
return attribs;
}
}
class Foo
{
[DisplayName("abc")]
[Browsable(false)]
public string Bar { get; set; }
}