Reflection - get attribute name and value on property

后端 未结 15 1864
谎友^
谎友^ 2020-11-22 04:59

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(\"         


        
相关标签:
15条回答
  • 2020-11-22 05:18

    Just looking for the right place to put this piece of code.

    let's say you have the following property:

    [Display(Name = "Solar Radiation (Average)", ShortName = "SolarRadiationAvg")]
    public int SolarRadiationAvgSensorId { get; set; }
    

    And you want to get the ShortName value. You can do:

    ((DisplayAttribute)(typeof(SensorsModel).GetProperty(SolarRadiationAvgSensorId).GetCustomAttribute(typeof(DisplayAttribute)))).ShortName;
    

    Or to make it general:

    internal static string GetPropertyAttributeShortName(string propertyName)
    {
        return ((DisplayAttribute)(typeof(SensorsModel).GetProperty(propertyName).GetCustomAttribute(typeof(DisplayAttribute)))).ShortName;
    }
    
    0 讨论(0)
  • 2020-11-22 05:19

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 05:19

    You can use GetCustomAttributesData() and GetCustomAttributes():

    var attributeData = typeof(Book).GetProperty("Name").GetCustomAttributesData();
    var attributes = typeof(Book).GetProperty("Name").GetCustomAttributes(false);
    
    0 讨论(0)
  • 2020-11-22 05:19
    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);
        }
    }
    

    Usage:

     //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();
    
    0 讨论(0)
  • 2020-11-22 05:20

    Necromancing.
    For those that still have to maintain .NET 2.0, or those that want to do it without LINQ:

    public static object GetAttribute(System.Reflection.MemberInfo mi, System.Type t)
    {
        object[] objs = mi.GetCustomAttributes(t, true);
    
        if (objs == null || objs.Length < 1)
            return null;
    
        return objs[0];
    }
    
    
    
    public static T GetAttribute<T>(System.Reflection.MemberInfo mi)
    {
        return (T)GetAttribute(mi, typeof(T));
    }
    
    
    public delegate TResult GetValue_t<in T, out TResult>(T arg1);
    
    public static TValue GetAttributValue<TAttribute, TValue>(System.Reflection.MemberInfo mi, GetValue_t<TAttribute, TValue> value) where TAttribute : System.Attribute
    {
        TAttribute[] objAtts = (TAttribute[])mi.GetCustomAttributes(typeof(TAttribute), true);
        TAttribute att = (objAtts == null || objAtts.Length < 1) ? default(TAttribute) : objAtts[0];
        // TAttribute att = (TAttribute)GetAttribute(mi, typeof(TAttribute));
    
        if (att != null)
        {
            return value(att);
        }
        return default(TValue);
    }
    

    Example usage:

    System.Reflection.FieldInfo fi = t.GetField("PrintBackground");
    wkHtmlOptionNameAttribute att = GetAttribute<wkHtmlOptionNameAttribute>(fi);
    string name = GetAttributValue<wkHtmlOptionNameAttribute, string>(fi, delegate(wkHtmlOptionNameAttribute a){ return a.Name;});
    

    or simply

    string aname = GetAttributValue<wkHtmlOptionNameAttribute, string>(fi, a => a.Name );
    
    0 讨论(0)
  • 2020-11-22 05:28

    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; }
    }
    
    0 讨论(0)
提交回复
热议问题