如何从不同的域转换Lambda表达式?

时间:2018-06-18 14:36:49

标签: c# lambda expression expression-trees linq-expressions

我试图将Lambda表达式从域转换为另一个域。 这是我收到的参数:

Expression<Func<Entities.UserRight, bool>> expression

我应该返回类型

的表达式
Expression<Func<UserRight,bool>> 

UserRight和Entities.UserRight都是相同的型号,但属于不同的块包。

我试图通过:

public Expression<Func<UserRight,bool>> ConvertExpression(Expression<Func<Entities.UserRight, bool>> expression)
    {
        var resultBody = Expression.Convert(expression.Body, typeof(UserRight));
        var result = Expression.Lambda<Func<UserRight, bool>>(resultBody, expression.Parameters);
        return result;
    }

但是我收到了InvalidOperationException错误

1 个答案:

答案 0 :(得分:0)

假设我们有两个类Address1和Address2,如下所示:

class Address1
{
    public string City { get; set; }
    public string Detail { get; set; }
}

class Address2
{
    public string City { get; set; }
    public string Detail { get; set; }
}

并且有一个类似Address1的表达式:

Expression<Func<Address1, string>> getCityName = ad1 => ad1.City;

我们可以通过ExpressionVisitor将表达式更改为可用于Address2:

public class ExpressionConvertor: ExpressionVisitor
{
    private ParameterExpression ad2Parameter;
    public ExpressionConvertor(ParameterExpression ad2Parameter)
    {
        this.ad2Parameter = ad2Parameter;
    }

    public override Expression Visit(Expression node)
    {
        if(node is LambdaExpression node2)
        {
            var exp = base.Visit(node2.Body);
            return Expression.Lambda(exp, ad2Parameter);
        }
        return base.Visit(node);
    }

    protected override Expression VisitMember(MemberExpression node)
    {       
        if(node.Expression is ParameterExpression)
            return Expression.PropertyOrField(ad2Parameter, node.Member.Name);

        return base.VisitMember(node);
    }
}

最后我们像这样使用此类:

Expression<Func<Address1, string>> getCityName = ad1 => ad1.City;

var ad2Parameter = Expression.Parameter(typeof(Address2), "ad2");
var convertor = new ExpressionConvertor(ad2Parameter);
var getCityName2 = (Expression<Func<Address2, string>>)convertor.Visit(getCityName);
var getCityName2Method = getCityName2.Compile();

var addr2 = new Address2()
{
    City = "MyCity",
    Detail = "My Address Detail"
};
var cityName = getCityName2Method(addr2);
Console.WriteLine(cityName); //MyCity