将lambda表达式转换为包装类

时间:2018-01-03 17:33:18

标签: c# lambda

鉴于类型:

public class MyClass
{
    public string Prop { get; set; }
}

public class MyWrapper
{
   public MyWrapper(MyClass myClass)
   {
       MyClass = myClass;
   }

   public MyClass MyClass { get; }
}

是否可以将Expression<Func<MyClass, bool>>类型的谓词表达式转换为Expression<Func<MyWrapper, bool>>

e.g。有这样的方法:

public Expression<Func<MyWrapper, bool>> Convert(Expression<Func<MyClass, bool>> predicate)
{
    return ...
}

以便调用Convert(obj => obj.Prop == "ABC")将返回wrapper => wrapper.MyClass.Prop == "ABC"

1 个答案:

答案 0 :(得分:1)

您需要使用ExpressonVisitor访问传入的谓词的主体,并将类型MyClass的每个参数更改为MyClass类型的MyWrapper参数的成员访问权限1}}。最后,您将新构造的主体构造为具有类型MyWrapper的参数作为参数的新lambda表达式。

访客样本:

public class ConverterVisitor : ExpressionVisitor
{
    public ConverterVisitor(ParameterExpression original, Expression convertTo)
    {
        OriginalParameter = original;
        ConvertTo = convertTo;
    }

    public ParameterExpression OriginalParameter { get; }

    public Expression ConvertTo { get; }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        if (OriginalParameter == node)
        {
            return ConvertTo;
        }
        return base.VisitParameter(node);
    }
}

Convert方法的示例:

public Expression<Func<MyWrapper, bool>> Convert(Expression<Func<MyClass, bool>> predicate)
{
    var originalParameter = predicate.Parameters[0];
    var newParameter = Expression.Parameter(typeof(MyWrapper));
    var ma = Expression.Property(newParameter, nameof(MyWrapper.MyClass));
    var converter = new ConverterVisitor(originalParameter, ma);
    var newBody = converter.Visit(predicate.Body);
    return Expression.Lambda<Func<MyWrapper, bool>>(newBody, newParameter);
}