Est-il possible d'ajouter des attributs au moment de l'exécution ou de modifier la valeur d'un attribut au moment de l'exécution?
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, le System.Type
classe est simplement une représentation réfléchie 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 paramètre System.ComponentModel.TypeDescriptor peut être utilisé pour ajouter des attributs à des types, des propriétés et des instances d'objet. Il présente également la limitation que vous devez l'utiliser pour récupérer ces propriétés. Si vous écrivez le code qui utilise ces attributs et que vous pouvez respecter ces limitations, je le recommanderais 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 comme ça qu'ils font environ la moitié des choses qu'ils doivent vraiment faire.
Tu ne peux pas. Une solution de contournement pourrait consister à générer une classe dérivée au moment de l’exécution et à ajouter l’attribut, bien que ce soit probablement un peu excessif.
Eh bien, juste pour être différent, j'ai trouvé un article qui fait référence à 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 des approches possibles sont discutés.
Non ce n'est pas.
Les attributs sont des méta-données et stockés sous forme binaire dans l’Assemblée compilée (c’est 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 ajouter 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 les attributs, mais est finalement passé à la sérialisation avec xml.
Pourquoi avez-vous besoin de Les attributs donnent des informations supplémentaires pour la réflexion, mais si vous savez en externe quelles propriétés vous souhaitez, vous n'en avez pas besoin.
Vous pouvez stocker les métadonnées de manière externe relativement facilement dans une base de données ou un fichier de ressources.
J'ai essayé très fort avec System.ComponentModel.TypeDescriptor sans succès. Cela ne signifie pas 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 à cette fin.
// ************************************************************************
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);
}
}
}