Est-il possible d'ajouter des attributs lors de l'exécution ou de modifier la valeur d'un attribut lors de l'exécution?
Est-il possible d'ajouter des attributs lors de l'exécution ou de modifier la valeur d'un attribut lors de l'exécution?
Réponses:
Les attributs sont des métadonnées statiques. Les assemblys, modules, types, membres, paramètres et valeurs de retour ne sont pas des objets de première classe en C # (par exemple, la System.Type
classe est simplement une représentation reflétée d'un type). Vous pouvez obtenir une instance d'un attribut pour un type et modifier les propriétés si elles sont accessibles en écriture, mais cela n'affectera pas l'attribut tel qu'il est appliqué au type.
Cela dépend vraiment de ce que vous essayez d'accomplir.
Le truc System.ComponentModel.TypeDescriptor peut être utilisé pour ajouter des attributs à des types, des propriétés et des instances d'objet, et il a la limitation que vous devez l'utiliser pour récupérer ces propriétés également. Si vous écrivez le code qui consomme ces attributs et que vous pouvez vivre dans ces limites, je le suggérerais certainement.
Autant que je sache, le contrôle PropertyGrid et la surface de conception de Visual Studio sont les seuls éléments de la BCL qui consomment les éléments TypeDescriptor. En fait, c'est ainsi qu'ils font environ la moitié des choses dont ils ont vraiment besoin.
TypeDescriptor
et TypeDescriptionProvider
ne sont-elles pas implémentées?
[Attr(1), Attr(2), Attr(3)]
seul Attr(3)
est trouvé.
Eh bien, juste pour être différent, j'ai trouvé un article qui fait référence à l'utilisation de Reflection.Emit pour le faire.
Voici le lien: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , vous voudrez également examiner certains des commentaires au bas de l'article, car les approches possibles sont discutées.
YourClass
dans YourRuntimeClassWithAttributes
.
YourClass
, vous pouvez la sous- classer au moment de l'exécution et générer une classe identique avec un nom légèrement différent qui a également les attributs créés dynamiquement souhaités, et le polymorphisme permettra au code de vérification de type de toujours identifier votre classe de base.
Non ce n'est pas.
Les attributs sont des méta-données et stockés sous forme binaire dans l'assembly compilé (c'est aussi pourquoi vous ne pouvez utiliser que des types simples).
Je ne crois pas. Même si je me trompe, le mieux que vous puissiez espérer est de les ajouter à un type entier, jamais à une instance d'un type.
Si vous avez besoin de quelque chose pour pouvoir être ajouté dynamiquement, les attributs c # ne sont pas la solution. Regardez dans le stockage des données au format XML. J'ai récemment fait un projet que j'ai commencé avec des attributs, mais qui est finalement passé à la sérialisation avec xml.
Pourquoi en avez-vous besoin? Les attributs donnent des informations supplémentaires pour la réflexion, mais si vous savez de l'extérieur quelles propriétés vous voulez, vous n'en avez pas besoin.
Vous pouvez stocker des métadonnées en externe assez facilement dans une base de données ou un fichier de ressources.
J'ai essayé très dur avec System.ComponentModel.TypeDescriptor sans succès. Cela ne veut pas dire que cela ne peut pas fonctionner, mais j'aimerais voir du code pour cela.
En contrepartie, je voulais changer certaines valeurs d'attribut. J'ai fait 2 fonctions qui fonctionnent bien à cet effet.
// ************************************************************************
public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, description);
}
}
}
// ************************************************************************
public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
{
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
if (att != null)
{
var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldDescription != null)
{
fieldDescription.SetValue(att, isReadOnly);
}
}
}
En Java, j'avais l'habitude de contourner ce problème en utilisant une carte et en implémentant ma propre vision du codage clé-valeur.
http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html
TypeDescriptor
- pas seulementPropertyGrid
.