您的位置:首页 > 编程语言 > C#

C#之Expression表达式目录树

2022-03-14 23:50 1691 查看

一、Expression是什么

1、和委托的区别

a、委托是编译时,表达式目录树是运行时,在应用程序运行过程中可以重新赋值

b、委托相当于是拿到别人dll文件,只能调用里面的方法;表达式目录树相当于拿到了别人的源码,可以进行扩展

2、Expression本质

a、表达式目录树是一个类的封装,描述了一个结构,有身体部分和参数部分

b、表达式目录树展开后的每一个节点也是一个表达式目录树

二、Expression动态拼接

1、最基础版本

Expression<Func<int>> expression = () => 123 + 456;

ConstantExpression constant1= Expression.Constant(123,typeof(int));
ConstantExpression constant2 = Expression.Constant(456, typeof(int));
BinaryExpression binaryExpression =Expression.Add(constant1, constant2);
Expression<Func<int>> expressionReslut = Expression.Lambda<Func<int>>(binaryExpression,Array.Empty<ParameterExpression>());

Func<int> func = expressionReslut.Compile();
var result = func.Invoke();

 

2、带参数版本

Expression<Func<int,int>> expression = m => m + 123;

ParameterExpression parameterExpression =Expression.Parameter(typeof(int),"m");
ConstantExpression constantExpression = Expression.Constant(123, typeof(int));
BinaryExpression binaryExpression =Expression.Add(parameterExpression, constantExpression);
Expression<Func<int,int>> expressionReslut = Expression.Lambda<Func<int,int>>(binaryExpression, new ParameterExpression[1]

parameterExpression
});

Func<int,int> func = expressionReslut.Compile();
var result = func.Invoke(10);

 

3、带有多个参数

Expression<Func<int, int, int>> expression = (m, n) => m * n + 2;

ParameterExpression parameterExpressionM = Expression.Parameter(typeof(int), "m");
ParameterExpression parameterExpressionN = Expression.Parameter(typeof(int), "n");
BinaryExpression multiply = Expression.Multiply(parameterExpressionM, parameterExpressionN);
ConstantExpression constantExpression = Expression.Constant(2);
BinaryExpression plus = Expression.Add(multiply, constantExpression);
Expression<Func<int, int, int>> expression1 = Expression.Lambda<Func<int, int, int>>(plus, new ParameterExpression[2
{
parameterExpressionM,
parameterExpressionN
});
Func<int, int, int> func1 = expression1.Compile();
int iResult1 = func1.Invoke(20, 30);

4、对象字段值比较

如果碰到很长的表达式目录树,建议先拼装右边,再拼装左边

Expression<Func<User, bool>> expression = (x) => x.Id.ToString() == "1" && x.Name.Equals("xiaohemiao");

// 1、声明参数
ParameterExpression parameterExpression=Expression.Parameter(typeof(User),"x");
// 2、因为要拼装x.Name,所以要先找到Name
PropertyInfo propName = typeof(User).GetProperty("Name");
// 3、拼装x.Name
MemberExpression memberExpression = Expression.Property(parameterExpression, propName);
// 4、因为需要调用Equals,所以要先获取Equals方法
MethodInfo methodInfo= typeof(string).GetMethod("Equals",new Type[] { typeof(string)});
// 5、调用Equals方法,x.Name.Equals("xiaohemiao") ,调用需要“xiaohemiao”,所以先声明一个字符串常量
ConstantExpression constantExpressionRight =Expression.Constant("xiaohemiao", typeof(string));
// 6、拼装x.Name.Equals("xiaohemiao")
MethodCallExpression MethodCallExpressionRight=Expression.Call(memberExpression, methodInfo, constantExpressionRight);
// 7、开始拼装左边 拼装x.Id,所以先找到Id
PropertyInfo propId = typeof(User).GetProperty("Id");
// 8、拼装x.Id
MemberExpression memberExpressionId = Expression.Property(parameterExpression, propId);
// 9、因为要拼装x.Id.ToString(),所以先找到ToString方法
MethodInfo toString = typeof(int).GetMethod("ToString", new Type[0] { });
// 10、开始拼装x.Id.ToString()
MethodCallExpression methodCallExpressionLeft1=Expression.Call(memberExpressionId, toString, Array.Empty<Expression>());
// 11、需要声明一个常量
ConstantExpression constantExpressionLeft= Expression.Constant("1",typeof(string));
// 12、拼装x.Id.ToString().Equals("1"),需要调用Equals方法,先获取Equals方法--上面已经获取过,可以直接使用
BinaryExpression BinaryExpression = Expression.Equal(methodCallExpressionLeft1,  constantExpressionLeft);
// 13、左边和右边都拼装好了,现在要把左边和右边 && 起来
BinaryExpression binaryExpression=Expression.AndAlso(BinaryExpression, MethodCallExpressionRight);

Expression<Func<User, bool>> expression1 = Expression.Lambda<Func<User, bool>>(binaryExpression, new ParameterExpression[1]
{
parameterExpression
});

Func<User, bool> func = expression1.Compile();
var result = func.Invoke(new User() {
Id=1,
Name="xiaohemiao"
});

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: