Check if property has attribute

前端 未结 8 1534
刺人心
刺人心 2020-11-28 03:03

Given a property in a class, with attributes - what is the fastest way to determine if it contains a given attribute? For example:

    [IsNotNullable]
    [I         


        
相关标签:
8条回答
  • 2020-11-28 03:21

    This is a pretty old question but I used

    My method has this parameter but it could be built:

    Expression<Func<TModel, TValue>> expression
    

    Then in the method this:

    System.Linq.Expressions.MemberExpression memberExpression 
           = expression.Body as System.Linq.Expressions.MemberExpression;
    Boolean hasIdentityAttr = System.Attribute
           .IsDefined(memberExpression.Member, typeof(IsIdentity));
    
    0 讨论(0)
  • 2020-11-28 03:29

    There's no fast way to retrieve attributes. But code ought to look like this (credit to Aaronaught):

    var t = typeof(YourClass);
    var pi = t.GetProperty("Id");
    var hasIsIdentity = Attribute.IsDefined(pi, typeof(IsIdentity));
    

    If you need to retrieve attribute properties then

    var t = typeof(YourClass);
    var pi = t.GetProperty("Id");
    var attr = (IsIdentity[])pi.GetCustomAttributes(typeof(IsIdentity), false);
    if (attr.Length > 0) {
        // Use attr[0], you'll need foreach on attr if MultiUse is true
    }
    
    0 讨论(0)
  • 2020-11-28 03:31

    If you are using .NET 3.5 you might try with Expression trees. It is safer than reflection:

    class CustomAttribute : Attribute { }
    
    class Program
    {
        [Custom]
        public int Id { get; set; }
    
        static void Main()
        {
            Expression<Func<Program, int>> expression = p => p.Id;
            var memberExpression = (MemberExpression)expression.Body;
            bool hasCustomAttribute = memberExpression
                .Member
                .GetCustomAttributes(typeof(CustomAttribute), false).Length > 0;
        }
    }
    
    0 讨论(0)
  • 2020-11-28 03:33

    If you are trying to do that in a Portable Class Library PCL (like me), then here is how you can do it :)

    public class Foo
    {
       public string A {get;set;}
    
       [Special]
       public string B {get;set;}   
    }
    
    var type = typeof(Foo);
    
    var specialProperties = type.GetRuntimeProperties()
         .Where(pi => pi.PropertyType == typeof (string) 
          && pi.GetCustomAttributes<Special>(true).Any());
    

    You can then check on the number of properties that have this special property if you need to.

    0 讨论(0)
  • 2020-11-28 03:36

    This can now be done without expression trees and extension methods in a type safe manner with the new C# feature nameof() like this:

    Attribute.IsDefined(typeof(YourClass).GetProperty(nameof(YourClass.Id)), typeof(IsIdentity));
    

    nameof() was introduced in C# 6

    0 讨论(0)
  • 2020-11-28 03:37

    To update and/or enhance the answer by @Hans Passant I would separate the retrieval of the property into an extension method. This has the added benefit of removing the nasty magic string in the method GetProperty()

    public static class PropertyHelper<T>
    {
        public static PropertyInfo GetProperty<TValue>(
            Expression<Func<T, TValue>> selector)
        {
            Expression body = selector;
            if (body is LambdaExpression)
            {
                body = ((LambdaExpression)body).Body;
            }
            switch (body.NodeType)
            {
                case ExpressionType.MemberAccess:
                    return (PropertyInfo)((MemberExpression)body).Member;
                default:
                    throw new InvalidOperationException();
            }
        }
    }
    

    Your test is then reduced to two lines

    var property = PropertyHelper<MyClass>.GetProperty(x => x.MyProperty);
    Attribute.IsDefined(property, typeof(MyPropertyAttribute));
    
    0 讨论(0)
提交回复
热议问题