转换表达式树

让它有:

Expression<Func> exp1 = x => x.mesID == 1; Expression<Func> exp2 = x => x.mesID == 1; 

现在我需要将exp1传递给_db.Messages.where(exp1); 问题是我只有exp2,我需要将类型转换为Message,所有属性都是一样的!

现在我这样做:

  var par = Expression.Parameter(typeof(Message)); var ex = (Expression<Func>)Expression.Lambda(exp2.Body, par); 

问题是输入参数改变了是的! 但是lambda“x.mesID”正文中的x属于旧类型。

任何方式改变身体中的所有参数类型或改变输入参数,它反映身体呢?

我想这是我一直对LINQ的一个大问题,因为在层之间我不能传递生成的类,因为这将使层耦合,所以我必须制作轻量级类,现在我如何使用像_db.Messages这样的方法。哪里(); 从busiess层?!! 虽然busniess层对Message类型一无所知,但它只知道MessageDTO。

不,基本上。 表达式树是不可变的,并且包含完整成员元数据(即, mesIDmessageDTO.mesID )。 为此,您必须从头开始重建表达式树(通过访问者),处理您需要支持的每个节点类型。

如果表达式树是基本的,这应该没问题,但是如果你需要支持整个色域? 一个庞大的PITA(特别是在.NET 4中,它增加了更多的节点类型)。


一个基本的例子,它完成了示例所需的内容; 您需要为更复杂的表达式添加更多节点类型:

 using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; static class Program { static void Main() { Expression> exp1 = x => x.mesID == 1; var exp2 = Convert(exp1); } static Expression> Convert(Expression> expr) { Dictionary substitutues = new Dictionary(); var oldParam = expr.Parameters[0]; var newParam = Expression.Parameter(typeof(TTo), oldParam.Name); substitutues.Add(oldParam, newParam); Expression body = ConvertNode(expr.Body, substitutues); return Expression.Lambda>(body, newParam); } static Expression ConvertNode(Expression node, IDictionary subst) { if (node == null) return null; if (subst.ContainsKey(node)) return subst[node]; switch (node.NodeType) { case ExpressionType.Constant: return node; case ExpressionType.MemberAccess: { var me = (MemberExpression)node; var newNode = ConvertNode(me.Expression, subst); return Expression.MakeMemberAccess(newNode, newNode.Type.GetMember(me.Member.Name).Single()); } case ExpressionType.Equal: /* will probably work for a range of common binary-expressions */ { var be = (BinaryExpression)node; return Expression.MakeBinary(be.NodeType, ConvertNode(be.Left, subst), ConvertNode(be.Right, subst), be.IsLiftedToNull, be.Method); } default: throw new NotSupportedException(node.NodeType.ToString()); } } } class Message { public int mesID { get; set; } } class MessageDTO { public int mesID { get; set; } }