转置或翻译Expression Linq

时间:2012-03-10 07:39:45

标签: linq

我有viewmodel(比如memberviewmodel)和ef模型(比如成员)。我如何翻译

> GetByProperty(Expression<Func<MemberViewModel, bool>> whereCondition)

> GetByProperty(Expression<Func<Member, bool>> whereCondition)

任何想法?

我的服务公开方法GetByProperty(Expression&gt; whereCondition),但随后在服务中,它调用公开方法GetByProperty(Expression&gt; whereCondition)的业务对象。

1 个答案:

答案 0 :(得分:1)

要将Expression<Func<MemberViewModel, bool>>转换为Expression<Func<Member, bool>>,您需要扩展ExpressionVisitor课程。我假设MemberViewModel只包含字段和属性。 Member当然需要实现相同的字段和属性集。在这种情况下,以下应该有效:

public class ParameterModifier<TSrc, TDest> : ExpressionVisitor
{
    ParameterExpression parameter;

    public ParameterModifier()
    {
        parameter = Expression.Parameter(typeof(TDest), "member");
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        if (node.Type == typeof(TSrc))
        {
            return parameter;
        }
        else
            return base.VisitParameter(node);
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Expression.Type == typeof(TSrc))
        {
            return Expression.PropertyOrField(Visit(node.Expression), node.Member.Name);
        }
        else
        {
            return base.VisitMember(node);
        }
    }

    protected override Expression VisitLambda<T>(Expression<T> node)
    {
        if (node.Parameters.Any(p => p.Type == typeof(TSrc)))
        {
            return Expression.Lambda(Visit(node.Body), node.Parameters.Select(p => p.Type == typeof(TSrc) ? parameter : p));
        }
        else
        {
            return base.VisitLambda<T>(node);
        }
    }
}

在将谓词传递给第二种方法之前,您现在可以使用上面的类转换它:

IEnumerable<MemberViewModel> GetByProperty(Expression<Func<MemberViewModel, bool>> whereCondition)
{
    var converter = new ParameterModifier<MemberViewModel, Member>();
    var convertedExpression = converter.Visit(original) as Expression<Func<Member, bool>>;
    IEnumerable<Member> members = GetByProperty(convertedExpression);
    return members.Select(new MemberViewModel(member));
}