2016-01-26 11 views
5

ich folgenden Code haben:in C# als variable Teil eines Ausdrucks definieren

public class MyClass<T> 
{ 
    Expression<Func<T,bool>> Criteria {get; set;} 
} 
public class Customer 
{ 
    //.. 
    public string Name {get; set;} 
} 

und verwenden Sie es wie folgt:

var c = new MyClass<Customer>(); 
c.Criteria = x.Name.StartWith("SomeTexts"); 

Gibt es eine Möglichkeit, so etwas zu definieren:

Ich verwendete Expression<Func<T,bool>>, um es als WHERE-Klausel in meiner linq to entities Abfrage (EF-Code zuerst) zu verwenden.

+0

Ist 'p' ein' Ausdruck > 'oder ein' Func '? – gmiley

+0

Sollen 'c.Criteria = x.Name.StartWith (" SomeTexts ");' be 'c.Criteria = x => x.Name.StartWith (" SomeTexts ");'? –

+0

@YacoubMassad: Sie haben Recht :) – Masoud

Antwort

2

Sie können die folgenden Hilfsfunktionen (je einer wahrscheinlich ihnen einen besseren Namen geben könnte , aber das ist nicht unbedingt erforderlich):

public static class ExpressionUtils 
{ 
    public static Expression<Func<TOuter, TResult>> Bind<TOuter, TInner, TResult>(this Expression<Func<TOuter, TInner>> source, Expression<Func<TInner, TResult>> resultSelector) 
    { 
     var body = new ParameterExpressionReplacer { source = resultSelector.Parameters[0], target = source.Body }.Visit(resultSelector.Body); 
     var lambda = Expression.Lambda<Func<TOuter, TResult>>(body, source.Parameters); 
     return lambda; 
    } 

    public static Expression<Func<TOuter, TResult>> ApplyTo<TInner, TResult, TOuter>(this Expression<Func<TInner, TResult>> source, Expression<Func<TOuter, TInner>> innerSelector) 
    { 
     return innerSelector.Bind(source); 
    } 

    class ParameterExpressionReplacer : ExpressionVisitor 
    { 
     public ParameterExpression source; 
     public Expression target; 
     protected override Expression VisitParameter(ParameterExpression node) 
     { 
      return node == source ? target : base.VisitParameter(node); 
     } 
    } 
} 

Let sehen, wie die Probe Ausdruck

c.Criteria = x => x.Name.StartsWith("SomeTexts"); 

kann aus den zwei verschiedenen Teilen gebaut werden.

Wenn Sie

Expression<Func<Customer, string>> e = x => x.Name; 

dann

c.Criteria = e.Bind(x => x.StartsWith("SomeTexts")); 

oder wenn Sie diese stattdessen

Expression<Func<string, bool>> e = x => x.StartsWith("SomeTexts"); 

dann

c.Criteria = e.ApplyTo((Customer x) => x.Name); 

Wenn Sie beide Ausdrücke haben, können Sie eine der beiden Funktionen verwenden, da a.Bind(b)b.ApplyTo(a) entspricht.

0

Sie müssen Typ Variable explizit, aber das nächste Code definieren wird Ihnen helfen, Ihr Szenario zu lösen:

// define new expression that get an Order object and returns string value 
Expression<Func<Order, string>> p = x => x.Customer.Name; 
var c = new MyClass<Order>(); 

// Compile the expression to the Func then invoke it and call extra criteria 
c.Criteria = o => p.Compile().Invoke(o).StartsWith("SomeText"); 

Es gibt wenig einfachere Lösung ohne Ausdrücke:

Func<Order, string> p = x => x.Customer.Name; 
var c = new MyClass<Order>(); 
c.Criteria = o => p(o).StartsWith("SomeText"); 

Sie können auch Func<> anstelle von Expression<> in MyClass:

public MyClass<T> 
{ 
    Func<T,bool> Criteria {get; set;} 
} 
0

Ich sehe den Vorteil der Verwendung eines Expression hier nicht. Wie wäre es mit einem geraden Func?

public class MyClass<T> 
{ 
    public Func<T, string, bool> Criteria { get; set; } 
} 

Und dann ...

var myCustomer = new MyClass<Customer> 
{ 
    Criteria = (c, s) => c.Name.StartsWith(s) 
}; 

var customer = new Customer { Name = "Bob" }; 

var x = myCustomer.Criteria(customer, "B"); 
+0

Ich möchte Ausdruck > als ein Kriterium in meinem Linq zu Abfrage im EF-Code zuerst zu verwenden. – Masoud

0

Wenn Sie einen Ausdruck möchten, dann können Sie LinqKit verwenden folgendes zu tun:

Expression<Func<Customer, string>> p = x => x.Name; 

var c = new MyClass<Customer>(); 

c.Criteria = x => p.Invoke(x).StartsWith("asd"); //Reuse p expression 

c.Criteria = c.Criteria.Expand(); 

Invoke ist eine Erweiterung Methode von LinqKit bereitgestellt das hilft Ihnen, Ausdrücke leicht zu verfassen.

Nach der Expand Methode aufgerufen würde c.Criteria einen Ausdruck enthält, ist genau das gleiche, als wenn Sie dies getan haben:

c.Criteria = x => x.Name.StartsWith("asd"); 
Verwandte Themen