我有一个类,叫它Book,它的属性叫Name。有了这个属性,我就有了一个与之关联的属性。

public class Book
{
    [Author("AuthorName")]
    public string Name
    {
        get; private set; 
    }
}

在我的主要方法中,我使用反射,并希望获得每个属性的每个属性的键值对。因此,在本例中,我希望看到属性名为“Author”,属性值为“AuthorName”。

问:如何使用反射获取属性上的属性名和值?


当前回答

要获取一个属性在字典中的所有属性,请使用以下命令:

typeof(Book)
  .GetProperty("Name")
  .GetCustomAttributes(false) 
  .ToDictionary(a => a.GetType().Name, a => a);

如果您还想包含继承的属性,请记住从false更改为true。

其他回答

你可以使用GetCustomAttributesData()和GetCustomAttributes():

var attributeData = typeof(Book).GetProperty("Name").GetCustomAttributesData();
var attributes = typeof(Book).GetProperty("Name").GetCustomAttributes(false);

如果你只想要一个特定的属性值,例如Display Attribute,你可以使用以下代码:

var pInfo = typeof(Book).GetProperty("Name")
                             .GetCustomAttribute<DisplayAttribute>();
var name = pInfo.Name;
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();

这里有一些静态方法,可以用来获取MaxLength或任何其他属性。

using System;
using System.Linq;
using System.Reflection;
using System.ComponentModel.DataAnnotations;
using System.Linq.Expressions;

public static class AttributeHelpers {

public static Int32 GetMaxLength<T>(Expression<Func<T,string>> propertyExpression) {
    return GetPropertyAttributeValue<T,string,MaxLengthAttribute,Int32>(propertyExpression,attr => attr.Length);
}

//Optional Extension method
public static Int32 GetMaxLength<T>(this T instance,Expression<Func<T,string>> propertyExpression) {
    return GetMaxLength<T>(propertyExpression);
}


//Required generic method to get any property attribute from any class
public static TValue GetPropertyAttributeValue<T, TOut, TAttribute, TValue>(Expression<Func<T,TOut>> propertyExpression,Func<TAttribute,TValue> valueSelector) where TAttribute : Attribute {
    var expression = (MemberExpression)propertyExpression.Body;
    var propertyInfo = (PropertyInfo)expression.Member;
    var attr = propertyInfo.GetCustomAttributes(typeof(TAttribute),true).FirstOrDefault() as TAttribute;

    if (attr==null) {
        throw new MissingMemberException(typeof(T).Name+"."+propertyInfo.Name,typeof(TAttribute).Name);
    }

    return valueSelector(attr);
}

}

使用静态方法…

var length = AttributeHelpers.GetMaxLength<Player>(x => x.PlayerName);

或者在实例上使用可选的扩展方法…

var player = new Player();
var length = player.GetMaxLength(x => x.PlayerName);

或者对任何其他属性使用完整的静态方法(例如StringLength)…

var length = AttributeHelpers.GetPropertyAttributeValue<Player,string,StringLengthAttribute,Int32>(prop => prop.PlayerName,attr => attr.MaximumLength);

受到Mikael Engver回答的启发。

我已经通过编写一个通用扩展属性属性助手解决了类似的问题:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

public static class AttributeHelper
{
    public static TValue GetPropertyAttributeValue<T, TOut, TAttribute, TValue>(
        Expression<Func<T, TOut>> propertyExpression, 
        Func<TAttribute, TValue> valueSelector) 
        where TAttribute : Attribute
    {
        var expression = (MemberExpression) propertyExpression.Body;
        var propertyInfo = (PropertyInfo) expression.Member;
        var attr = propertyInfo.GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() as TAttribute;
        return attr != null ? valueSelector(attr) : default(TValue);
    }
}

用法:

var author = AttributeHelper.GetPropertyAttributeValue<Book, string, AuthorAttribute, string>(prop => prop.Name, attr => attr.Author);
// author = "AuthorName"