简体   繁体   English

动态构建表达式树

[英]Dynamically construct an expression tree

I have the following setup: 我有以下设置:

public class ProductSpecification {  
    public string Name { get; set; }
    public string Value { get; set; }
}

public class Product {  
    public IEnumerable<ProductSpecification> Specifications { get; set; }
}

I want to construct the following ExpressionTree in C# programmatically: 我想以编程方式在C#中构造以下ExpressionTree

p => p.Specifications.Any(s=>s.Name.Contains("name_val") && s.Value.Contains("value_val"))

I've managed to do this so far, but not even close to the end result: 到目前为止,我已经做到了,但是还没有达到最终结果:

public ExpressionBuilder AndStartsWith(string property, string value)
    {
        var arguments = new Dictionary<object, Type>
        {
            { value, typeof(string)},
            { StringComparison.InvariantCultureIgnoreCase, typeof(StringComparison)}
        };

        MethodCallExpression methodExpression = GetExpressionMethod(property, "StartsWith", arguments);
        _accumulator = Expression.AndAlso(_accumulator, methodExpression);

        return this;
    }

private MethodCallExpression GetExpressionMethod(string property, string methodName, Dictionary<object, Type> arguments) {
        MethodInfo method = typeof(string).GetMethod(methodName, arguments.Values.ToArray());
        Expression source = GetExpressionBody(property);
        IEnumerable<ConstantExpression> argumentsExpressions = arguments.Select(x => Expression.Constant(x.Key, x.Value));
        MethodCallExpression methodExpression = Expression.Call(source, method, argumentsExpressions);

        return methodExpression;
    }

Could you hint me to a solution? 您能提示我一个解决方案吗?

Hint, you can view the target expression tree you're trying to build by letting the compiler build it for you. 提示,可以让编译器为您构建目标表达式树,从而查看您要构建的目标表达式树。

Expression<Func<Product, bool>> expr = p =>
    p.Specifications.Any(s=>s.Name.Contains("name_val") && s.Value.Contains("value_val"));

Anyway, here's how you can build that expression: 无论如何,这是如何构建该表达式的方法:

public Expression<Func<Product, bool>> GenerateProductExpression()
{
    var param = Expression.Parameter(typeof(Product), "p");
    var nameValue = Expression.Constant("name_val");
    var valueValue = Expression.Constant("name_val");
    var specifications = Expression.Property(param, "Specifications");
    var body =
        Expression.Call(typeof(Enumerable), "Any", new[] { typeof(ProductSpecification) },
            specifications, GenerateAnyPredicate(nameValue, valueValue)
        );
    return Expression.Lambda<Func<Product, bool>>(body, param);
}

public Expression<Func<ProductSpecification, bool>> GenerateAnyPredicate(
        Expression nameValue, Expression valueValue)
{
    var param = Expression.Parameter(typeof(ProductSpecification), "s");
    var name = Expression.Property(param, "Name");
    var value = Expression.Property(param, "Value");
    var body = Expression.AndAlso(
        Expression.Call(name, "Contains", null, nameValue),
        Expression.Call(value, "Contains", null, valueValue)
    );
    return Expression.Lambda<Func<ProductSpecification, bool>>(body, param);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM