我有给定对象的表达式列表。我需要根据列表中提供的表达式为单独的对象创建匹配的表达式。目前,我正在尝试从表达式中手动提取属性,并为另一个对象重建新的表达式。
foreach(var clause in list)
{
//this needs to change since not all expressions are binary
var exp = clause as BinaryExpression;
var member = exp.Left as MemberExpression;
var otherObjectMember = Expression.Property(otherObject, member.Member.Name);
//member does not exist in otherObject
if (otherObjectMember == null)
continue;
//this needs to change to handle other expression types, not only equal
var otherObjectMemberCheck = Expression.Equal(otherObjectMember, exp.Right);
//additional processing...
}
上面的代码将在以下示例表达式列表中正常工作:
entity.Enabled == true
entity.Priority == 1
问题是,每个表达式类型的场景都必须手动处理(等于,不等于,包含等)。
以下表达式不起作用:
entity.Name.Contains("CPU")
values.Contains(entity.Name)
entity.Priority < 5
and any other non-binary expressions
我希望有更好的方法来处理这种表达式的重新分配。有人可以指出正确的方向吗? 预先感谢!
答案 0 :(得分:1)
您可以使用简单的ExpressionVisitor轻松完成此操作。
using System;
using System.Linq.Expressions;
public class Visitor : ExpressionVisitor
{
public ParameterExpression Target { get; set; }
public ParameterExpression Replacement { get; set; }
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Target ? Replacement : base.VisitParameter(node);
}
}
public class Program
{
public static void Main()
{
var obj = Expression.Variable(typeof(string));
var item = Expression.Property(obj, "Length");
var otherObj = Expression.Variable(typeof(string));
var replacedItem = new Visitor()
{
Target = obj,
Replacement = otherObj,
}.Visit(item);
}
}
访问者将递归访问表达式中的每个节点。找到ParameterExpression时,它将检查是否是我们要替换的变量:如果是,则返回替换值。最终结果是一个与输入相同的表达式,但是每次出现的目标变量都已被替换替换。
答案 1 :(得分:0)
您是否考虑过创建用于构建表达式的适配器对象。然后,您将为该单个Adapter对象拥有一个lambda。适配器应具有目标属性,并将其自身的属性映射到基础目标属性。然后,只需更改Adapter的Target属性即可为不同的对象提供表达式。
答案 2 :(得分:0)
这是一件很不容易的事情,因为它已经设置好了。目前,您基本上必须访问每个表达式的每个成员和值,然后希望以某种方式检测该表达式或将其投影到目标。
这是一个有缺陷的设计。
让您的生活更轻松的是简单地公开所有这些东西共享的界面。
public interface ISearchable
{
string Name { get; set; }
bool Enabled { get; set; }
int Priority { get; set; }
}
然后在可搜索实体上使用它
public class Machine : ISearchable {}
public class Part : ISearchable {}
然后在您的表情结构中
IList<Expression<Func<ISearchable,bool>>> list = new List <Expression<Func<ISearchable,bool>>>();
// apply entire list to ISearchable entities