转换表情树 [英] Convert Expression trees

查看:77
本文介绍了转换表情树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让它有:

Expression<Func<Message, bool>> exp1 = x => x.mesID == 1;
Expression<Func<MessageDTO, bool>> exp2 = x => x.mesID == 1;

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

now i need to pass exp1 to _db.Messages.where(exp1); problem is i only have exp2, i need to convert the type to Message , All properties are the same !

现在我这样做:

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

问题是输入参数被更改是!但是lambda"x.mesID"主体内部的x是旧类型.

problem with this is the input paramter gets changed yes ! but the x inside the body of the lambda "x.mesID" is of the old type.

是否也可以更改主体中所有参数的类型或更改也反映主体的输入参数?

any way to change all the parameters type in the body too or change the input parameter in away it reflect the body too ?

我想这是LINQ经常遇到的一个大问题,因为在各层之间我无法传递生成的类,因为这会使各层耦合,所以我必须制作轻量级的类,现在我该如何使用类似的方法_db.Messages.where();从繁忙的图层?虽然busniess层对消息类型一无所知,但仅知道MessageDTO.

i guess this is a big problem i always have with LINQ , since between layers i cant pass the generated classes , as this will make layers coupled , so i have to make light weight classes , now how do i use a method like _db.Messages.where(); from busiess layer ?!! while busniess layer doesnt know anything about Message type it only know MessageDTO.

推荐答案

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

No, basically. Expression trees are immutable, and contain full member meta-data (i.e. that mesID is messageDTO.mesID). To do this, you would have to rebuild the expression tree from scratch (via a visitor), handling every node type you need to support.

如果表达式树是 basic ,这应该可以,但是是否需要支持整个色域?一个巨大的PITA(尤其是在.NET 4中,它添加了更多的节点类型).

If the expression tree is basic this should be OK, but if you need to support the entire gamut? a huge PITA (especially in .NET 4, which adds a lot more node-types).

一个基本示例,可以做到恰好示例所需要的内容;您将需要添加更多节点类型以获取更复杂的表达式:

A basic example that does just what is required for the example; you would need to add more node-types for more complex expressions:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
static class Program
{
    static void Main()
    {
        Expression<Func<Message, bool>> exp1 = x => x.mesID == 1;
        var exp2 = Convert<Message, MessageDTO>(exp1);
    }
    static Expression<Func<TTo, bool>> Convert<TFrom, TTo>(Expression<Func<TFrom, bool>> expr)
    {
        Dictionary<Expression,Expression> substitutues = new Dictionary<Expression,Expression>();
        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<Func<TTo,bool>>(body, newParam);
    }
    static Expression ConvertNode(Expression node, IDictionary<Expression, Expression> 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; } }

这篇关于转换表情树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆