web-dev-qa-db-fra.com

Comment puis-je ajouter des propriétés à une classe lors de l'exécution en C #?

J'ai un cours :

class MyClass 
{
}
...
MyClass c = new MyClass();

Est-il possible d'ajouter des propriétés/champs à cette classe au moment de l'exécution?

( Je ne sais pas quels sont leurs types ou noms à la compilation et ils n'ont pas d'interface commune que je peux utiliser. )

exemple de pseudo:

 Add property named "Prop1" [type System.Int32]
 Add property named "Prop900" [type System.String]

J'ai déjà lu cette question mais il utilise l'interface

Merci d'avance.

15
Royi Namir

Vous ne pouvez pas étendre une classe existante avec de nouveaux membres lors de l'exécution. Cependant, vous pouvez créer une nouvelle classe en utilisant System.Reflection.Emit qui a la classe existante comme classe de base.

typeBuilder.SetParent(typeof(MyClass));
typeBuilder.DefineProperty("Prop1", ..., typeof(System.Int32), null);
...

Voir Méthode TypeBuilder.DefineProperty (String, PropertyAttributes, Type, Type []) pour un exemple complet.

32
dtb

Je pense que vous avez mal compris ce qu'est la réflexion. La réflexion ne vous permet pas de modifier le code que vous exécutez. Il peut vous permettre de lire votre propre code et même d'exécuter ce code.

Avec Reflection.Emit, vous pouvez écrire un tout nouvel assemblage, puis le charger en mémoire.

Cependant, vous NE POUVEZ PAS changer une classe au moment de l'exécution. Imaginez, vous avez une classe Foo, vous en installez tout un tas, puis décidez de changer de classe.

Que devrait-il arriver à tous les Foos que vous avez déjà instanciés?

Cependant, ce que vous POUVEZ faire, utilisez Reflection.Emit pour créer une nouvelle classe qui hérite de Foo, appelée Bar, puis ajoutez tout ce dont vous avez besoin à cette classe.

Alternativement, si vous souhaitez ajouter par programme une propriété à une classe APRÈS la compilation mais AVANT l'exécution, vous pouvez consulter IL Weaving/AOP. Je suggère de regarder PostSharp ou Fody si c'est ce qui vous intéresse.

5
Aron

Oui, vous pouvez utiliser la classe ExpandoObject pour y parvenir.

dynamic expando = new ExpandoObject();
expando.Prop1 = 10;
expando.Prop900 = string.Empty;
2
Daniel Hilgarth