C# Expression 和 Expression之间的转换
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# Expression 和 Expression之间的转换相关的知识,希望对你有一定的参考价值。
有两个类:
public class User
public int Id get; set;
public string Name get; set;
public class UserDto
public int Id get; set;
如何将:Expression<Func<UserDto, bool>> exp = item => item.Id.Equals(0); 转换成Expression<Func<User, bool>>
你这个都是C# 高级应用了。需要很多的代码呀!你参考一下吧。
namespace Systempublic static class LambdaExpressionExtensions
private static Expression Parser(ParameterExpression parameter, Expression expression)
if (expression == null) return null;
switch (expression.NodeType)
//一元运算符
case ExpressionType.Negate:
case ExpressionType.NegateChecked:
case ExpressionType.Not:
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
case ExpressionType.ArrayLength:
case ExpressionType.Quote:
case ExpressionType.TypeAs:
var unary = expression as UnaryExpression;
var exp = Parser(parameter, unary.Operand);
return Expression.MakeUnary(expression.NodeType, exp, unary.Type, unary.Method);
//二元运算符
case ExpressionType.Add:
case ExpressionType.AddChecked:
case ExpressionType.Subtract:
case ExpressionType.SubtractChecked:
case ExpressionType.Multiply:
case ExpressionType.MultiplyChecked:
case ExpressionType.Divide:
case ExpressionType.Modulo:
case ExpressionType.And:
case ExpressionType.AndAlso:
case ExpressionType.Or:
case ExpressionType.OrElse:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.Equal:
case ExpressionType.NotEqual:
case ExpressionType.Coalesce:
case ExpressionType.ArrayIndex:
case ExpressionType.RightShift:
case ExpressionType.LeftShift:
case ExpressionType.ExclusiveOr:
var binary = expression as BinaryExpression;
var left = Parser(parameter, binary.Left);
var right = Parser(parameter, binary.Right);
var conversion = Parser(parameter, binary.Conversion);
if (binary.NodeType == ExpressionType.Coalesce && binary.Conversion != null)
return Expression.Coalesce(left, right, conversion as LambdaExpression);
else
return Expression.MakeBinary(expression.NodeType, left, right, binary.IsLiftedToNull, binary.Method);
//其他
case ExpressionType.Call:
var call = expression as MethodCallExpression;
List<Expression> arguments = new List<Expression>();
foreach (var argument in call.Arguments)
arguments.Add(Parser(parameter, argument));
var instance = Parser(parameter, call.Object);
call = Expression.Call(instance, call.Method, arguments);
return call;
case ExpressionType.Lambda:
var Lambda = expression as LambdaExpression;
return Parser(parameter, Lambda.Body);
case ExpressionType.MemberAccess:
var memberAccess = expression as MemberExpression;
if (memberAccess.Expression == null)
memberAccess = Expression.MakeMemberAccess(null, memberAccess.Member);
else
var exp = Parser(parameter, memberAccess.Expression);
var member = exp.Type.GetMember(memberAccess.Member.Name).FirstOrDefault();
memberAccess = Expression.MakeMemberAccess(exp, member);
return memberAccess;
case ExpressionType.Parameter:
return parameter;
case ExpressionType.Constant:
return expression;
case ExpressionType.TypeIs:
var typeis = expression as TypeBinaryExpression;
var exp = Parser(parameter, typeis.Expression);
return Expression.TypeIs(exp, typeis.TypeOperand);
default:
throw new Exception(string.Format("Unhandled expression type: '0'", expression.NodeType));
public static Expression<Func<TToProperty, bool>> Cast<TInput, TToProperty>(this Expression<Func<TInput, bool>> expression)
var p = Expression.Parameter(typeof(TToProperty), "p");
var x = Parser(p, expression);
return Expression.Lambda<Func<TToProperty, bool>>(x, p);
下面是一个示例:
static int[] array0 = new[] 0, 1 ;
static void Main(string[] args)
//复杂表达式
var array1 = new[] 0, 1 ;
Expression<Func<UserDto, bool>> exp = u =>
u.Id.Equals(1)
&& u.Name == "张三"
&& u.Id < 10
&& array1.Contains(u.Id)
&& u.Id + 2 < 10
&& (((object)u.Id).ToString() == "1" || u.Name.Contains("三"))
&& Math.Abs(u.Id) == 1
&& Filter(u.Name)
&& true
;
Expression<Func<User, bool>> exp2 = exp.Cast<UserDto, User>();
//测试数据
List<User> list = new List<User>()
new User Id=0,Name="AAA",
new User Id=1,Name="张三",
new User Id=2,Name="李四"
;
var item = list.Where(exp2.Compile()).FirstOrDefault();
Console.WriteLine(item.Name);
Console.ReadKey();
public static bool Filter(string name)
return name.Contains("三");
应该说常用的筛选条件都是支持的。这里的list由于没有数据库环境就用List<User>模拟的,真实环境你换成list.Where(exp2)就可以了。
转换不了的,还是用接口实际点
public interface IUserint Idget;set;
public class User:IUser
public int Id get; set;
public string Name get; set;
public class UserDto:IUser
public int Id get; set;
Expression<Func<IUser, bool>> exp = item => item.Id.Equals(0);追问
你说得对,我也想过这种解决办法,可以解决问题
但是我记得AUTOMAPPER里面好像有这种解决方法!
AutoMapper使用笔记 - dudu - 博客园
http://www.cnblogs.com/dudu/archive/2011/12/16/2284828.html
你是指类似上面博客里的场景3那样的?
不是!
Oracle decode
DECODE()函数,它将输入数值与函数中的参数列表相比较,根据输入值返回一个对应值。函数的参数列表是由若干数值及其对应结果值组成的若干序偶形式。当然如果未能与任何一个实参序偶匹配成功,则函数也有默认的返回值。
语法结构如下:
decode (expression, sch_1, res_1)
decode (expression, sch_1, res_1, sch_2, res_2)
decode (expression, sch_1, res_1, sch_2, res_2, ...., sch_n, res_n)
decode (expression, sch_1, res_1, default)
decode (expression, sch_1, res_1, sch_2, res_2, default)
decode (expression, sch_1, res_1, sch_2, res_2, ...., sch_n, res_n, default)
比较表达式和搜索字,如果匹配,返回结果;如果不匹配,返回default值;如果未定义default值,则返回空值。
以上是关于C# Expression 和 Expression之间的转换的主要内容,如果未能解决你的问题,请参考以下文章