我有以下设置:
public class ProductSpecification {
public string Name { get; set; }
public string Value { get; set; }
}
public class Product {
public IEnumerable<ProductSpecification> Specifications { get; set; }
}
我想以编程方式在C#中构建以下ExpressionTree
:
p => p.Specifications.Any(s=>s.Name.Contains("name_val") && s.Value.Contains("value_val"))
到目前为止,我已设法做到这一点,但甚至没有接近最终结果:
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;
}
你能暗示我一个解决方案吗?
答案 0 :(得分:1)
提示,您可以通过让编译器为您构建它来查看您尝试构建的目标表达式树。
Expression<Func<Product, bool>> expr = p =>
p.Specifications.Any(s=>s.Name.Contains("name_val") && s.Value.Contains("value_val"));
无论如何,这是你如何构建那个表达式:
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);
}