Advertisement
Advertisement


Reflection - get attribute name and value on property


Question

I have a class, lets call it Book with a property called Name. With that property, I have an attribute associated with it.

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

In my main method, I'm using reflection and wish to get key value pair of each attribute for each property. So in this example, I'd expect to see "Author" for attribute name and "AuthorName" for the attribute value.

Question: How do I get the attribute name and value on my properties using Reflection?

2011/07/09
1
256
7/9/2011 9:45:37 PM

Accepted Answer

Use typeof(Book).GetProperties() to get an array of PropertyInfo instances. Then use GetCustomAttributes() on each PropertyInfo to see if any of them have the Author Attribute type. If they do, you can get the name of the property from the property info and the attribute values from the attribute.

Something along these lines to scan a type for properties that have a specific attribute type and to return data in a dictionary (note that this can be made more dynamic by passing types into the routine):

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;
}
2019/05/16
311
5/16/2019 11:04:15 AM

To get all attributes of a property in a dictionary use this:

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

remember to change from false to true if you want to include inheritted attributes as well.

2019/08/15

If you just want one specific Attribute value For instance Display Attribute you can use the following code:

var pInfo = typeof(Book).GetProperty("Name")
                             .GetCustomAttribute<DisplayAttribute>();
var name = pInfo.Name;
2018/12/25

I have solved similar problems by writing a Generic Extension Property Attribute Helper:

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);
    }
}

Usage:

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

You can use GetCustomAttributesData() and GetCustomAttributes():

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

If you mean "for attributes that take one parameter, list the attribute-names and the parameter-value", then this is easier in .NET 4.5 via the 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; }
}
2012/10/25

Source: https://stackoverflow.com/questions/6637679
Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]