Reflection - get attribute name and value on property

后端 未结 15 1873
谎友^
谎友^ 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:11

    Here are some static methods you can use to get the MaxLength, or any other attribute.

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

    Using the static method...

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

    Or using the optional extension method on an instance...

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

    Or using the full static method for any other attribute (StringLength for example)...

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

    Inspired by the Mikael Engver's answer.

    0 讨论(0)
  • 2020-11-22 05:12

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

    I wrote this into a dynamic method since I use lots of attributes throughout my application. Method:

    public static dynamic GetAttribute(Type objectType, string propertyName, Type attrType)
        {
            //get the property
            var property = objectType.GetProperty(propertyName);
    
            //check for object relation
            return property.GetCustomAttributes().FirstOrDefault(x => x.GetType() == attrType);
        }
    

    Usage:

    var objectRelAttr = GetAttribute(typeof(Person), "Country", typeof(ObjectRelationAttribute));
    
    var displayNameAttr = GetAttribute(typeof(Product), "Category", typeof(DisplayNameAttribute));
    

    Hope this helps anyone

    0 讨论(0)
  • 2020-11-22 05:16

    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.

    0 讨论(0)
  • 2020-11-22 05:17

    to get attribute from enum, i'm using :

     public enum ExceptionCodes
     {
      [ExceptionCode(1000)]
      InternalError,
     }
    
     public static (int code, string message) Translate(ExceptionCodes code)
            {
                return code.GetType()
                .GetField(Enum.GetName(typeof(ExceptionCodes), code))
                .GetCustomAttributes(false).Where((attr) =>
                {
                    return (attr is ExceptionCodeAttribute);
                }).Select(customAttr =>
                {
                    var attr = (customAttr as ExceptionCodeAttribute);
                    return (attr.Code, attr.FriendlyMessage);
                }).FirstOrDefault();
            }
    

    // Using

     var _message = Translate(code);
    
    0 讨论(0)
  • 2020-11-22 05:18
    private static Dictionary<string, string> GetAuthors()
    {
        return typeof(Book).GetProperties()
            .SelectMany(prop => prop.GetCustomAttributes())
            .OfType<AuthorAttribute>()
            .ToDictionary(a => a.GetType().Name.Replace("Attribute", ""), a => a.Name);
    }
    

    Example using generics (target framework 4.5)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    
    private static Dictionary<string, string> GetAttribute<TAttribute, TType>(
        Func<TAttribute, string> valueFunc)
        where TAttribute : Attribute
    {
        return typeof(TType).GetProperties()
            .SelectMany(p => p.GetCustomAttributes())
            .OfType<TAttribute>()
            .ToDictionary(a => a.GetType().Name.Replace("Attribute", ""), valueFunc);
    }
    

    Usage

    var dictionary = GetAttribute<AuthorAttribute, Book>(a => a.Name);
    
    0 讨论(0)
提交回复
热议问题