C# Expression Visitor
Posted zhaxichun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# Expression Visitor相关的知识,希望对你有一定的参考价值。
using System; using System.Linq; using System.Linq.Expressions; using System.Runtime.InteropServices; namespace app { public abstract class Visitor { private readonly Expression node; protected Visitor(Expression node) { this.node = node; } public abstract void Visit(string prefix); public ExpressionType NodeType => this.node.NodeType; public static Visitor CreateFormatExpression(Expression node) { switch (node.NodeType) { case ExpressionType.Constant: return new ConstantVisitor((ConstantExpression)node); case ExpressionType.Lambda: return new LambdaVisitor((LambdaExpression)node); case ExpressionType.Parameter: return new ParameterVisitor((ParameterExpression)node); case ExpressionType.Add: case ExpressionType.Equal: case ExpressionType.Multiply: return new BinaryVisitor((BinaryExpression)node); case ExpressionType.Conditional: return new ConditionalVisitor((ConditionalExpression)node); case ExpressionType.Call: return new MethodCallVisitor((MethodCallExpression)node); default: Console.Error.WriteLine($"Node not processed yet: {node.NodeType}"); return default(Visitor); } } } public class LambdaVisitor : Visitor { private readonly LambdaExpression node; public LambdaVisitor(LambdaExpression node) : base(node) { this.node = node; } public override void Visit(string prefix) { Console.WriteLine($"{prefix} this expession is a {NodeType} expression type"); Console.WriteLine($"{prefix} this name of the lambda is {((node.Name == null) ? "<null>": node.Name)}"); Console.WriteLine($"{prefix} the return is {node.ReturnType.ToString()}"); Console.WriteLine($"{prefix} the expression has {node.Parameters.Count} arguments.They are"); foreach (var argumentExpression in node.Parameters) { var argumentVisitor = Visitor.CreateFormatExpression(argumentExpression); argumentVisitor.Visit(prefix + ‘\t‘); } Console.WriteLine($"{prefix} The expression body is:"); var bodyVisitor = Visitor.CreateFormatExpression(node.Body); bodyVisitor.Visit(prefix + ‘\t‘); } } public class BinaryVisitor : Visitor { private readonly BinaryExpression node; public BinaryVisitor(BinaryExpression node) : base(node) { this.node = node; } public override void Visit(string prefix) { Console.WriteLine($"{prefix}This binary expression is a {NodeType} expression"); var left = Visitor.CreateFormatExpression(node.Left); Console.WriteLine($"{prefix}The Left argument is:"); left.Visit(prefix + "\t"); var right = Visitor.CreateFormatExpression(node.Right); Console.WriteLine($"{prefix}The Right argument is:"); right.Visit(prefix + "\t"); } } public class ParameterVisitor : Visitor { private readonly ParameterExpression node; public ParameterVisitor(ParameterExpression node) : base(node) { this.node = node; } public override void Visit(string prefix) { Console.WriteLine($"{prefix}This is an {NodeType} expression type"); Console.WriteLine($"{prefix}Type: {node.Type.ToString()}, Name: {node.Name}, ByRef: {node.IsByRef}"); } } public class ConstantVisitor : Visitor { private readonly ConstantExpression node; public ConstantVisitor(ConstantExpression node) : base(node) { this.node = node; } public override void Visit(string prefix) { Console.WriteLine($"{prefix}This is an {NodeType} expression type"); Console.WriteLine($"{prefix}The type of the constant value is {node.Type}"); Console.WriteLine($"{prefix}The value of the constant value is {node.Value}"); } } public class ConditionalVisitor : Visitor { private readonly ConditionalExpression node; public ConditionalVisitor(ConditionalExpression node) : base(node) { this.node = node; } public override void Visit(string prefix) { Console.WriteLine($"{prefix}This expression is a {NodeType} expression"); var testVisitor = Visitor.CreateFormatExpression(node.Test); Console.WriteLine($"{prefix}The Test for this expression is:"); testVisitor.Visit(prefix + "\t"); var trueVisitor = Visitor.CreateFormatExpression(node.IfTrue); Console.WriteLine($"{prefix}The True clause for this expression is:"); trueVisitor.Visit(prefix + "\t"); var falseVisitor = Visitor.CreateFormatExpression(node.IfFalse); Console.WriteLine($"{prefix}The False clause for this expression is:"); falseVisitor.Visit(prefix + "\t"); } } public class MethodCallVisitor : Visitor { private readonly MethodCallExpression node; public MethodCallVisitor(MethodCallExpression node) : base(node) { this.node = node; } public override void Visit(string prefix) { Console.WriteLine($"{prefix}This expression is a {NodeType} expression"); if (node.Object == null) Console.WriteLine($"{prefix}This is a static method call"); else { Console.WriteLine($"{prefix}The receiver (this) is:"); var receiverVisitor = Visitor.CreateFormatExpression(node.Object); receiverVisitor.Visit(prefix + "\t"); } var methodInfo = node.Method; Console.WriteLine($"{prefix}The method name is {methodInfo.DeclaringType}.{methodInfo.Name}"); // There is more here, like generic arguments, and so on. Console.WriteLine($"{prefix}The Arguments are:"); foreach(var arg in node.Arguments) { var argVisitor = Visitor.CreateFormatExpression(arg); argVisitor.Visit(prefix + "\t"); } } } }
以上是关于C# Expression Visitor的主要内容,如果未能解决你的问题,请参考以下文章
C# Expression 和 Expression之间的转换
System.Core 错误:使用 C# Entity Framework 和 Linq 和 Expression 的“代码应该无法访问”