C#表达式目录树示例详解表达式目录树示例详解
1、表达式目录树、表达式目录树
表达式目录树,在C#中是Expression来定义的,它是一种语法树,或者说是一种数据结构。其主要用于存储需要计算、
运算的一种结构,它只提供存储功能,不进行运算。通常Expression是配合Lambda一起使用,lambda可以是匿名方法。
Expression可以动态创建。
声明一个lambda表达式,其中可以指明类型,也可以是匿名方法:
//Func<int, int, int> func = new Func<int, int, int>((m, n) => m * n + 2);
Func<int, int, int> func = (m, n) => m * n + 2;
上述代码可以使用Expression来定义:
Expression<Func<int, int, int>> exp = (m, n) => m * n + 2;//lambda表达式声明表达式目录树
Expression的方法体只能是一个整体,不能具有花括号,以下代码是不允许的:
Expression<Func<int, int, int>> exp1 = (m, n) =>//方法体只能一体
{
return m * n + 2;
};
上述func和exp执行结果相同:
int iResult1 = func.Invoke(3, 2);
int iResult2 = exp.Compile().Invoke(3, 2);
2、构建表达式目录树、构建表达式目录树
上述表达式示例可以通过Expression来自主构建,把m、n定义为ParameterExpression参数,把2定义为常数表达式
ConstantExpression,使用Expression的静态方法,表示乘和加:
ParameterExpression parameterLeft = Expression.Parameter(typeof(int), "m");//定义参数
ParameterExpression parameterRight = Expression.Parameter(typeof(int), "n");//定义参数
BinaryExpression binaryMultiply = Expression.Multiply(parameterLeft, parameterRight);//组建第一步的乘法
ConstantExpression constant = Expression.Constant(2, typeof(int)); //定义常数参数
BinaryExpression binaryAdd = Expression.Add(binaryMultiply, constant);//组建第二步的加法
var expression = Expression.Lambda<Func<int, int, int>>(binaryAdd, parameterLeft, parameterRight);//构建表达式
var func = expression.Compile(); //编译为lambda表达式
int iResult3 = func(3, 2);
int iResult4 = expression.Compile().Invoke(3, 2);
int iResult5 = expression.Compile()(3, 2);
自主构建Expression是,参数名称的定义,可以不是m、n,可以是其他的a、b或者x、y。
如何构建一个复杂的表达式目录树?需要使用到Expression中更多的方法、属性、扩展方法等。首先定义一个类:
public class People
{
public int Age { get; set; }
public string Name { get; set; }
public int Id;
}
基于上面的类,构建表达式: Expression<Func<People, bool>> lambda = x => x.Id.ToString().Equals(“5”);
这个示例中,使用到了int自身的ToString()方法,还使用到了字符串的Equals方法。构建过程如下:
//以下表达式目录树实现lambda的表达式
Expression<Func<People, bool>> lambda = x => x.Id.ToString().Equals("5");
//声明一个参数对象
ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "x");
//查找字段, 并绑定访问参数对象字段(属性)的方法:x.Id
MemberExpression member = Expression.Field(parameterExpression, typeof(People).GetField("Id"));
//以上可以用这个代替
var temp =Expression.PropertyOrField(parameterExpression, "Id");
//调用字段的ToString方法:x.Id.ToString()
MethodCallExpression method = Expression.Call(member, typeof(int).GetMethod("ToString", new Type[] { }), new Expression[0]);