Comment : modifier des arborescences d'expression
Mise à jour : novembre 2007
Cette rubrique vous indique comment modifier une arborescence d'expression. Les arborescences d'expression sont immuables, ce qui signifie qu'elles ne peuvent pas être modifiées directement. Pour modifier une arborescence d'expression, vous devez créer une copie d'une arborescence d'expression existante et, lorsque vous créez la copie, apporter les modifications requises. Vous pouvez utiliser un visiteur de l'arborescence d'expression pour parcourir une arborescence d'expression existante et copier chaque nœud qu'il visite.
Pour modifier une arborescence d'expression
Dans Visual Studio, créez un projet Application console.
Ajoutez une référence à System.Core.dll si elle n'est pas déjà référencée.
Ajoutez la classe ExpressionVisitor à votre projet.
Ce code est disponible dans Comment : implémenter un visiteur de l'arborescence de l'expression.
Ajoutez des directives using (ou instructions Imports dans Visual Basic) au fichier pour les espaces de noms suivants : System.Collections.Generic, System.Collections.ObjectModel et System.Linq.Expressions.
Ajoutez la classe AndAlsoModifier à votre projet.
Cette classe hérite de la classe ExpressionVisitor et est spécialisée pour modifier les expressions qui représentent des opérations AND conditionnelles. Elle fait passer ces opérations d'un AND conditionnel à un OR conditionnel. Pour ce faire, la classe substitue la méthode VisitBinary du type de base, car les expressions AND conditionnelles sont représentées comme expressions binaires. Dans la méthode VisitBinary, si l'expression qui lui est passée représente une opération AND conditionnelle, le code construit une nouvelle expression qui contient l'opérateur OR conditionnel au lieu de l'opérateur AND conditionnel. Si l'expression passée à VisitBinary ne représente pas d'opération AND conditionnelle, la méthode diffère à l'implémentation de la classe de base. Les méthodes de la classe de base construisent des nœuds qui sont semblables aux arborescences d'expression passées, mais les sous-arbres des nœuds sont remplacés par les arborescences d'expression produites de manière récursive par le visiteur.
Public Class AndAlsoModifier Inherits ExpressionVisitor Public Function Modify(ByVal expr As Expression) As Expression Return Visit(expr) End Function Protected Overrides Function VisitBinary(ByVal b As BinaryExpression) As Expression If b.NodeType = ExpressionType.AndAlso Then Dim left = Me.Visit(b.Left) Dim right = Me.Visit(b.Right) ' Make this binary expression an OrElse operation instead ' of an AndAlso operation. Return Expression.MakeBinary(ExpressionType.OrElse, left, right, _ b.IsLiftedToNull, b.Method) End If Return MyBase.VisitBinary(b) End Function End Class
public class AndAlsoModifier : ExpressionVisitor { public Expression Modify(Expression expression) { return Visit(expression); } protected override Expression VisitBinary(BinaryExpression b) { if (b.NodeType == ExpressionType.AndAlso) { Expression left = this.Visit(b.Left); Expression right = this.Visit(b.Right); // Make this binary expression an OrElse operation instead of an AndAlso operation. return Expression.MakeBinary(ExpressionType.OrElse, left, right, b.IsLiftedToNull, b.Method); } return base.VisitBinary(b); } }
Ajoutez une directive using (ou instruction Imports dans Visual Basic) au fichier pour l'espace de noms System.Linq.Expressions.
Ajoutez du code à la méthode Main dans le fichier Program.cs (Module1.vb dans Visual Basic) pour créer une arborescence d'expression et passez-la à la méthode qui la modifiera.
Le code suivant crée une expression qui contient une opération AND conditionnelle. Il crée alors une instance de la classe AndAlsoModifier et passe l'expression à la méthode Modify de cette classe. L'arborescence d'expression d'origine et l'arborescence d'expression modifiée sont toutes deux sorties pour afficher la modification.
Dim expr As Expression(Of Func(Of String, Boolean)) = _ Function(name) name.Length > 10 AndAlso name.StartsWith("G") Console.WriteLine(expr) Dim modifier As New AndAlsoModifier() Dim modifiedExpr = modifier.Modify(CType(expr, Expression)) Console.WriteLine(modifiedExpr) ' This code produces the following output: ' name => ((name.Length > 10) && name.StartsWith("G")) ' name => ((name.Length > 10) || name.StartsWith("G"))
Expression<Func<string, bool>> expr = name => name.Length > 10 && name.StartsWith("G"); Console.WriteLine(expr); AndAlsoModifier treeModifier = new AndAlsoModifier(); Expression modifiedExpr = treeModifier.Modify((Expression) expr); Console.WriteLine(modifiedExpr); /* This code produces the following output: name => ((name.Length > 10) && name.StartsWith("G")) name => ((name.Length > 10) || name.StartsWith("G")) */
Ajoutez une directive using (ou instruction Imports dans Visual Basic) au fichier pour l'espace de noms System.Linq.Expressions.
Compilez et exécutez l'application.
Voir aussi
Tâches
Comment : exécuter des arborescences d'expression
Procédure pas à pas : création d'un fournisseur LINQ IQueryable
Comment : implémenter un visiteur de l'arborescence de l'expression