gpt4 book ai didi

c# - 转换表达式树

转载 作者:可可西里 更新时间:2023-11-01 09:07:45 28 4
gpt4 key购买 nike

让有:

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,所有属性都是一样的!

现在我这样做:

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

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

有什么方法可以更改正文中的所有参数类型或更改输入参数以反射(reflect)正文吗?

我想这是我在使用 LINQ 时一直遇到的一个大问题,因为在层之间我无法传递生成的类,因为这会使层耦合,所以我必须制作轻量级类,现在我该如何使用像这样的方法_db.Messages.where();来自业务层?!!而业务层对消息类型一无所知,它只知道 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<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; } }

关于c# - 转换表达式树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3667561/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com