2016-07-14 13 views
0

Ich habe folgendes Setup:dynamisch konstruieren einen Ausdruck Baum

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

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

Ich möchte programmatisch die folgende ExpressionTree in C# konstruieren:

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

Ich habe es geschafft, diese so weit zu tun, aber nicht einmal nahe am Endergebnis:

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; 
    } 

Können Sie mir eine Lösung vorschlagen?

Antwort

1

Hinweis: Sie können die Zielausdrucksstruktur anzeigen, die Sie erstellen möchten, indem Sie den Compiler für Sie erstellen lassen.

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

Wie auch immer, hier ist, wie man diesen Ausdruck aufbauen können:

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); 
} 
+0

Excellent Mann! Danke vielmals. –