4

EDIT: Je ferais mieux de reformuler: Comment puis-je déplacer l'implémentation GET d'une propriété de classe vers/en utilisant un attribut personnalisé? (je l'ai ajouté instantiation vars (classname, propertyName) à l'attribut, mais je préfère avoir ces relevé automatiquement ofcourse.)Attribut de propriété personnalisée .NET?

Public Class CustomClass 
    <CustomAttributeClass(ClassName:="CustomClass", PropertyName = "SomeProperty")> _ 
    Public Property SomeProperty() as String 
     Get() as String 
      //This implementation should be handled by the attribute class 
     End Get 

     Set(Byval value as String) 
      Me._someProperty = value 
     End Set 
    End Property 
End Class 

vieille question:

Je veux créer un attribut de propriété personnalisée pour les classes. Je peux créer une classe dérivée de l'attribut, et marquer la propriété avec l'attribut, mais où aller à partir d'ici?

J'ai un référentiel où je peux obtenir rapidement des données basées sur les valeurs d'attributs. Je voudrais généraliser le comportement de la propriété dans l'attribut mais je ne sais pas comment aller d'ici ... Toute aide serait grandement acceptée!

Public Class CustomDataAttribute : Inherits Attribute 
    Private _name As String 

    Public Sub New(ByVal name As String) 
     Me.Name = name 
    End Sub 

    Property Name() As String 
     Get 
      Return _name 
     End Get 
     Set(ByVal value As String) 
      Me._name = value 
     End Set 
    End Property 
End Class 


Public Class CustomClass 
    <CustomDataAttribute(Name:="CustomField")> _ 
    Public Property CustomField() 
    End Property 
End Class 
+0

Où aller d'ici? Où essayez-vous d'obtenir? Qu'essayez-vous d'accomplir? – Oded

+0

La CustomClass est une classe de données qui stocke les données dans la table qui lui est associée. Je souhaite remplacer plusieurs propriétés et les stocker dans une table distincte (ainsi que d'autres propriétés d'autres classes personnalisées nécessitant des données à extraire de leur propre table) – Ropstah

Répondre

2

Vous devrez utiliser Reflection pour découvrir l'attribut. Dans votre cas, vous l'obtiendrez à partir de PropertyInfo.GetCustomAttributes().

La partie la plus difficile de l'utilisation des attributs consiste à trouver un modèle d'exécution approprié pour les utiliser réellement. Quelque chose comme un compilateur, un concepteur ou une classe qui sérialise des objets est une évidence. L'utilité des attributs s'envole rapidement à partir de là. C'est presque toujours le mauvais choix lorsque vous essayez d'utiliser un attribut où une propriété virtuelle est réellement nécessaire. La récupération des valeurs d'attribut est très coûteuse, de nombreux ordres de grandeur plus coûteux que la récupération d'une valeur de propriété. Utilisez-les uniquement lorsque le code de réflexion s'exécute au moment humain (comme les compilateurs) ou lorsque le coût est insignifiant par rapport au bénéfice ou à la surcharge (courant dans tout type d'opération d'E/S).

+0

Pouvez-vous préciser: Je souhaite appliquer la localisation aux propriétés des objets métier personnalisés . L'attribution/attribution de propriétés est-elle une très mauvaise façon de procéder? S'il n'y avait qu'une seule propriété par objet, je créerais une interface pour définir la propriété-à-localiser. Cependant, plusieurs propriétés par objet doivent être localisées. Aucune suggestion? – Ropstah

+0

"très" cher n'est pas tout à fait raison. Techniquement plus cher qu'un appel de méthode, oui. Mais les modèles orientés attribut sont utilisés dans tout le monde .NET dans les systèmes qui sont * extrêmement * sensibles aux performances. L'utilisation d'attributs dans votre système ne sera pas le goulot d'étranglement. –

+0

Mais je ne sais pas où aller avec le réflecteur. Il semble étrange de regarder ce que j'essaie d'accomplir ... N'y a-t-il pas un attribut de propriété de base qui a des événements comme onGet et onSet? – Ropstah

2

De vos commentaires à la réponse précédente, je pense que vous trouverez que les attributs .NET ne sont pas aussi flexibles que vous le souhaitez.

Vous avez demandé "N'y at-il pas un attribut de propriété de base qui a des événements comme onGet et onSet?" -- non; les attributs n'ont aucune interaction intégrée avec leurs cibles, que ce soit des méthodes ou des classes. En fait, vous ne pouvez même pas dire au moment de l'exécution quelle est la cible d'un attribut; Vous devez d'abord connaître la cible (classe, méthode, propriété, etc.), puis interroger les attributs qui la décorent. En second lieu, les attributs ne sont pas réellement créés jusqu'à ce que vous demandiez pour eux. Lorsque vous appelez GetCustomAttributes, le système d'exécution évalue les métadonnées de l'assembly et instancie les attributs spécifiés. Si vous l'appelez deux fois de suite, vous obtiendrez deux ensembles des mêmes attributs. Pour revenir à votre autre question: si vous voulez savoir quand une propriété décorée avec vos attributs est définie ou récupérée, vous devez implémenter INotifyPropertyChanged sur toutes vos classes liées, écrire du code pour rechercher toutes vos classes pour propriétés marquées avec cet attribut lors du chargement de l'assembly, puis créer une interactivité qui a relié les événements PropertyChanged au code que vous avez besoin de déclencher. (Et cela ne vous informe que sur set opérations, pas get.)

Aucune idée si cela est utile, mais c'est parti. :-)

+0

des informations secondaires très utiles pour quelqu'un qui n'a pas fait plus avec des attributs qu'un attribut d'autorisation personnalisé. Cependant je ne sais toujours pas où aller à partir d'ici ... J'ai juste besoin de changer certaines classes commerciales déjà existantes pour avoir certaines propriétés à localiser ... Je ne peux pas utiliser le fournisseur de ressources par défaut car cela stocke un chemin de la vue rendre les ressources locales. Cependant j'ai besoin de localiser (en ce qui concerne les ressources locales, pas la localisation! Lol) les ressources basées sur les classes métier, pas sur les vues basées ... – Ropstah

0

Voici une classe qui aide au traitement des attributs personnalisés lors de l'utilisation de la réflexion. Passez le type en paramètre au constructeur.

public class AttributeList : List<Attribute> 
{ 
    /// <summary> 
    /// Gets a list of custom attributes 
    /// </summary> 
    /// <param name="propertyInfo"></param> 
    /// <returns></returns> 
    public static AttributeList GetCustomAttributeList(ICustomAttributeProvider propertyInfo) 
    { 
     var result = new AttributeList(); 
     result.AddRange(propertyInfo.GetCustomAttributes(false).Cast<Attribute>()); 
     return result; 
    } 

    /// <summary> 
    /// Finds attribute in collection by its own type or parents type 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <returns></returns> 
    public T FindAttribute<T>() where T : Attribute 
    { 
     return (T)Find(x => typeof(T).IsAssignableFrom(x.GetType())); 
    } 

    /// <summary> 
    /// Finds attribute in collection by its own type or parents type 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <returns></returns> 
    public List<T> FindAllAttributes<T>() where T : Attribute 
    { 
     return new List<T>(FindAll(x => typeof(T).IsAssignableFrom(x.GetType())).Cast<T>()); 
    } 

    /// <summary> 
    /// Finds attribute in collection by its own type or parents type 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <returns></returns> 
    public List<T> FindAllAttributes<T>(Type implementsType) where T : Attribute 
    { 
     return new List<T>(FindAll(x => implementsType.IsAssignableFrom(x.GetType())).Cast<T>()); 
    } 

    public bool IsAttributeSet<T>() where T : Attribute 
    { 
     return FindAttribute<T>() != null; 
    } 

    public TValue GetValueFromAttributeOrDefault<TAttr, TValue>(Func<TAttr, TValue> func, TValue defaultValue) 
     where TAttr : Attribute 
    { 
     var attribute = FindAttribute<TAttr>(); 
     return attribute == null ? 
      defaultValue : 
      func(attribute); 
    } 
}