2010-06-08 3 views
6

Dans les frameworks .NET 2.0-3.5, LCG (aka la classe DynamicMethod) était un moyen décent d'émettre des méthodes allégées lors de l'exécution lorsqu'aucune structure de classe n'était nécessaire pour les supporter. Dans .NET 4.0, les arborescences d'expression prennent désormais en charge les instructions et les blocs et, à ce titre, offrent suffisamment de fonctionnalités pour créer à peu près toutes les fonctionnalités d'une telle méthode, et peuvent être construites de manière beaucoup plus simple et sûre que d'émettre directement les codes op CIL. (Cette affirmation est issue de l'expérience actuelle de conversion de certains de nos codes LCG les plus complexes pour utiliser la construction et la compilation d'expressions à la place.)La génération de code léger (LCG) est-elle morte?

Y a-t-il une raison pour utiliser le LCG dans un nouveau code? Y at-il quelque chose qu'il peut faire que les arbres d'expression ne peuvent pas faire? Ou est-ce maintenant une fonctionnalité «morte»?

Répondre

1

Eh bien, cette question est assez ancienne maintenant, et j'attends un tf get pour terminer ... alors je vais y répondre moi-même.

Oui, LCG est mort dans la plupart des cas.

Nous avions l'habitude de faire un peu d'utilisation de LCG et il a maintenant été converti pour utiliser des arbres d'expression à la place. Ils sont beaucoup plus faciles à construire, le code est nettement plus facile à maintenir et à déboguer, et les messages d'erreur sont généralement plus informatifs que «l'opération pourrait déstabiliser l'exécution» lorsque vous avez des problèmes lors du développement. Mais, peut-être le plus important, les arbres d'expression sont composables d'une manière que Reflection.Emit ne l'est pas. Cela signifie que l'architecture des composants utilisés pour la génération de code d'exécution peut être plus modulaire et même permettre aux plugins d'étendre la structure de génération de code.

La seule chose que j'ai trouvé qui est pris en charge par Reflection.Emit qui n'est pas directement pris en charge dans les arborescences d'expression est la définition des champs .initonly. Cependant, cela peut être réalisé en utilisant une petite classe d'aide et de l'invoquer dans l'arbre d'expression, par exemple celui que j'utilisé est ci-dessous:

internal static class FieldHelper 
{ 
    public static TTarget AssignInitOnlyField<TTarget, TField>(
     TTarget target, string fieldName, TField value) 
    { 
     var field = target.GetType().GetField(
      fieldName, 
      BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); 
     var boxed = (object)target; // required for value type support 
     field.SetValue(boxed, value); 
     return (TTarget)boxed; 
    } 
} 

Il convient de mentionner l'un vers le bas-côté en utilisant des arbres d'expression plutôt que LCG est que la construction et la compilation des arbres d'expression est nettement plus lente que d'émettre directement les codes op bruts. En supposant que vous mettez en cache les méthodes compilées, il est peu probable que ce soit un problème important, mais c'est la seule raison qui pourrait vous obliger à utiliser LCG.

+0

La réponse est clairement non. LCG est précisément utile car il permet de compiler IL dans l'exécution, ce qui le rend beaucoup plus performant. Si vous n'avez pas besoin du code construit pour être rapide, vous n'en avez pas besoin. Donc, fondamentalement, LCG a toujours son créneau. – Benja

3

Il ne sert à rien de construire CIL directement sans étapes intermédiaires. Mais il est parfaitement possible d'utiliser vos propres langages intermédiaires qui ciblent l'IL à la fin. Les arbres d'expression, etc., ne sont pas suffisants - il s'agit d'une seule langue, alors que lors de la mise en œuvre des DSL, vous avez besoin de plusieurs sémantiques différentes. Vous pouvez émettre du code facilement dangereux (avec beaucoup de ldftns et similaires), vous pouvez émettre des appels de queue (pas sûr si c'est possible avec des expressions), des appels non virtuels vers des méthodes virtuelles, vous pouvez efficacement construire des automates d'état avec des étiquettes et les sauts, etc. Les arbres d'expressions sont si limitants que je ne peux tout simplement pas comprendre comment ils peuvent être comparés à un CIL brut.

0

Le LCG fait référence à des méthodes qui peuvent être collectées après leur sortie du cadre. Les expressions LINQ utilisent LCG ou émission normale de réflexion ... Donc LCG n'est définitivement pas mort. De plus, les expressions LINQ ne supportent pas tout comme les paramètres ref, ldtoken, les méthodes d'instance, les propriétés, etc.

0

Les arborescences d'expressions sont certainement un moyen d'optimiser le code généré lors de l'exécution.Cependant, vous devez clairement comprendre que c'est limité et ne vous donne pas accès à toute la puissance du langage MSIL. LGC et ILGenerator vont donc certainement rester pour les tâches les plus exigeantes.

Questions connexes