51 votes

Reflection.Emit et CodeDOM

Quels sont les avantages et les inconvénients de l'utilisation de la bibliothèque Reflection.Emit par rapport à CodeDOM pour la génération dynamique de code au moment de l'exécution ?

J'essaie de générer des classes dynamiques (relativement complexes) dans un système basé sur des métadonnées disponibles au moment de l'exécution sous forme XML. Je vais générer des classes qui étendent les classes existantes dans l'assemblage de l'application, en implémentant des interfaces supplémentaires, en ajoutant des méthodes, et en surchargeant les membres virtuels et abstraits.

Je veux m'assurer que je choisis la technique appropriée avant de m'engager trop profondément dans la mise en œuvre. Toute information sur les différences entre ces différentes techniques de génération de code serait utile. De même, toute information sur les bibliothèques open-source qui simplifient ou rationalisent le travail avec l'une ou l'autre des API serait également utile.

61voto

Tomas Petricek Points 118959

Je pense que les points clés concernant CodeDOM et Reflection.Emit sont les suivants :

  • CodeDom génère du code source C# et est généralement utilisé pour générer du code à inclure dans une solution et à compiler dans l'IDE (par exemple, les classes LINQ to SQL, WSDL, XSD fonctionnent toutes de cette manière). Dans ce scénario, vous pouvez également utiliser des classes partielles pour personnaliser le code généré. Cette méthode est moins efficace, car elle génère du code source C# et fait ensuite tourner le compilateur pour l'analyser (encore !) et le compiler. Vous pouvez générer du code en utilisant des constructions de relativement haut niveau (similaires aux expressions et instructions C#) telles que les boucles.

  • Reflection.Emit génère un IL de sorte qu'il produit directement un assemblage qui peut également être stocké uniquement en mémoire. Vous devez générer du code IL de bas niveau (les valeurs sont stockées sur la pile ; les boucles doivent être implémentées en utilisant des sauts), donc générer une logique plus complexe est un peu difficile.

En général, je pense que Reflection.Emit est considéré comme le moyen préféré de générer du code au moment de l'exécution, tandis que CodeDOM est préféré pour générer du code avant la compilation. Dans votre scénario, les deux méthodes fonctionneraient probablement bien (bien que CodeDOM ait besoin de privilèges plus élevés, car il doit invoquer le compilateur C#, qui fait partie de toute installation .NET).

Une autre option serait d'utiliser le Expression classe . Dans .NET 4.0, il vous permet de générer du code équivalent aux expressions et aux instructions C#. Cependant, il ne vous permet pas de générer des classes. Vous pouvez donc combiner cette fonction avec Reflection.Emit (pour générer des classes qui délèguent la mise en œuvre au code généré à l'aide de la fonction Expression ). Pour certains scénarios, vous n'avez pas vraiment besoin d'une hiérarchie de classes complète - souvent, un dictionnaire de délégués générés dynamiquement, tels que Dictionary<string, Action> pourrait être suffisant (mais bien sûr, cela dépend de votre scénario exact).

16voto

Tim Robinson Points 28696

Le code qui cible CodeDom a tendance à être plus facile à maintenir, puisque vous générez du code C# et non IL (plus de personnes peuvent lire le C# que l'IL). En outre, si vous vous trompez dans votre code CodeDom, vous obtenez une erreur de compilation ; si vous générez un IL invalide, vous obtenez une exception fatale ou un crash.

Cependant, comme CodeDom invoque le csc.exe il est un peu plus lent de rendre le code prêt à être utilisé. Avec Reflection.Emit, vous pouvez générer du code directement en mémoire.

Le CodeDom est probablement parfait pour la plupart des choses ; les XmlSerializer et le concepteur WinForms l'utilisent.

7voto

Vlad Points 23480

Vous pouvez consulter ExpandoObject . Cependant, il s'agit de .NET 4.0 uniquement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X