web-dev-qa-db-fra.com

Vérifier si la propriété a un attribut

Étant donné une propriété dans une classe, avec des attributs - quel est le moyen le plus rapide de déterminer si elle contient un attribut donné? Par exemple:

    [IsNotNullable]
    [IsPK]
    [IsIdentity]
    [SequenceNameAttribute("Id")]
    public Int32 Id
    {
        get
        {
            return _Id;
        }
        set
        {
            _Id = value;
        }
    }

Quelle est la méthode la plus rapide pour déterminer, par exemple, qu’elle possède l’attribut "IsIdentity"?

147
Otávio Décio

Il n'y a pas de moyen rapide de récupérer des attributs. Mais le code devrait ressembler à ceci (crédit à Aaronaught ):

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

Si vous devez récupérer les propriétés d'attribut alors

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
}
252
Hans Passant

Si vous utilisez .NET 3.5, vous pouvez essayer des arbres d’expression. C'est plus sûr que la réflexion:

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;
    }
}
43
Darin Dimitrov

Vous pouvez utiliser une méthode commune (générique) pour lire un attribut sur un MemberInfo donné.

public static bool TryGetAttribute<T>(MemberInfo memberInfo, out T customAttribute) where T: Attribute {
                var attributes = memberInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault();
                if (attributes == null) {
                    customAttribute = null;
                    return false;
                }
                customAttribute = (T)attributes;
                return true;
            }
12
Manish Basantani

Pour mettre à jour et/ou améliorer la réponse de @Hans Passant, je séparerais la récupération de la propriété en une méthode d'extension. Cela a l'avantage supplémentaire de supprimer la chaîne magique méchante de la méthode 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();
        }
    }
}

Votre test est alors réduit à deux lignes

var property = PropertyHelper<MyClass>.GetProperty(x => x.MyProperty);
Attribute.IsDefined(property, typeof(MyPropertyAttribute));
7
Seb

Si vous essayez de faire cela dans une bibliothèque de classes portable PCL (comme moi), voici comment vous pouvez le faire :)

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

Vous pouvez ensuite vérifier le nombre de propriétés qui possèdent cette propriété spéciale si vous en avez besoin.

7
Has AlTaiar

Vous pouvez utiliser la méthode Attribute.IsDefined

https://msdn.Microsoft.com/en-us/library/system.attribute.isdefined (v = vs.110) .aspx

if(Attribute.IsDefined(YourProperty,typeof(YourAttribute)))
{
    //Conditional execution...
}

Vous pouvez fournir la propriété que vous recherchez ou vous pouvez parcourir l'ensemble en utilisant la réflexion, par exemple:

PropertyInfo[] props = typeof(YourClass).GetProperties();
4
Francis Musignac

Cela peut maintenant être fait sans arborescence d'expression et sans méthodes d'extension de manière sécurisée contre le type avec la nouvelle fonctionnalité C # nameof() comme ceci:

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

nameof () a été introduit en C # 6

3
Jim Wolff

C'est une question assez ancienne mais j'ai utilisé

Ma méthode a ce paramètre mais il pourrait être construit:

Expression<Func<TModel, TValue>> expression

Puis dans la méthode ceci:

System.Linq.Expressions.MemberExpression memberExpression 
       = expression.Body as System.Linq.Expressions.MemberExpression;
Boolean hasIdentityAttr = System.Attribute
       .IsDefined(memberExpression.Member, typeof(IsIdentity));
2
Mark Schultheiss