2013-05-21 13 views
6

ho qualcosa di simile a questo:Restituzione di espressione <> utilizzando varie proprietà della classe

public Expression<Func<Message, bool>> FilterData() 
{ 
    switch (this.operatorEnum) 
    { 
     case FilterParameterOperatorEnum.EqualTo: 
      return message => !string.IsNullOrEmpty(message.Body) && 
           message.Body 
            .Equals(this.value, StringComparison.InvariantCultureIgnoreCase); 

     case FilterParameterOperatorEnum.NotEqualTo: 

      return message => !string.IsNullOrEmpty(message.Body) && 
           !message.Body 
            .Equals(this.value, StringComparison.InvariantCultureIgnoreCase); 

     case FilterParameterOperatorEnum.Contains: 

      return message => 
        !string.IsNullOrEmpty(message.Body) && 
        message.Body.IndexOf(this.value, 
            StringComparison.InvariantCultureIgnoreCase) >= 0; 

     case FilterParameterOperatorEnum.DoesNotContain: 
      return message => 
        !string.IsNullOrEmpty(message.Body) && 
        message.Body.IndexOf(this.value, 
            StringComparison.InvariantCultureIgnoreCase) == -1; 


    } 
} 

Come si può vedere che questo è fatto su Message.Body

io ora cosa fare la stessa cosa su altre proprietà di stringa su la classe Message e non voglio duplicare tutto quel codice.

C'è un modo per farlo passando in qualche modo nella proprietà?

risposta

1

Puoi provare a comporre l'espressione completamente manualmente, che ti darà la possibilità di specificare il nome della proprietà come una stringa. Questa non è una soluzione completa ed è testato, ma può dare un punto di partenza per capire cosa intendo:

var parameter = Expression.Parameter(typeof(Message), "o"); 
var getname = Expression.Property(parameter, "Body"); 

var isnullorempty = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, getname)); 
var compare = Expression.Equal(getname, Expression.Constant("thisvalue")); 

var combined = Expression.And(isnullorempty, compare); 

var lambda = Expression.Lambda(combined, parameter); 

Così si cambierebbe la funzione di accettare "Body" come parametro, e poi gettato il lambda alla fine di:

expression<func<Message, bool>> 

Probabilmente non ho ottenuto la sintassi per la creazione del lambda esattamente però.

0

Basta modificare la funzione per ricevere la proprietà anziché il messaggio.

Oppure il modo più difficile passa un altro parametro per il nome della proprietà e selezionarlo tramite riflessione.

Modifica solo per un'opzione di modifica per tutte le opzioni.

public Func<Message, string, bool> FilterData() 
    { 
     return (message, propName) => 
     { 
      var prop = message.GetType().GetProperty(propName); 

      if(prop != null){ 
       var propValue = (string)prop.GetValue(message,null); 
       return !string.IsNullOrEmpty(propValue) && ...; 
      } 
      return false; 
     }; 

    } 
+0

E cosa fa il corpo di FilterData assomiglia? – Jon

+0

Per fare ciò correttamente, dopo aver controllato che 'prop' non è' null', dovresti anche assicurarti che 'prop.CanRead' sia' true'. –

3

Eclude l'espressione che recupera il valore della proprietà in un'espressione lambda separata:

public Expression<Func<Message, bool>> FilterData(Func<Message, string> retrievePropValueFunc) 

Nelle tue espressioni di filtro, è possibile quindi chiamare quella nuova espressione lambda (solo mostrando uno come esempio):

return message => !string.IsNullOrEmpty(retrievePropValueFunc(message)) 
     && retrievePropValueFunc(message) 
       .Equals(this.value, StringComparison.InvariantCultureIgnoreCase); 

per raggiungere la proprietà Body, passare message => message.Body al parametro retrievePropValueFunc; come puoi vedere, puoi modificarlo per passare anche diverse espressioni lambda per il recupero di altre proprietà.

+0

Il 'retrievePropValueFunc' deve essere un' Expression > '? –

+0

Attualmente ottengo "Il tipo di nodo di espressione LINQ" Invoke "non è supportato in LINQ alle entità." – Jon

+0

@SteveGreatrex come si chiama retrievePropValueFunc se è un'espressione – Jon

0

Un approccio molto veloce e sporco potrebbe essere un enum più una sorta di magia:

public enum FilterTarget { Body, AnyOtherProp }; 
public Expression<Func<Message, bool>> FilterData(FilterTarget filterTarget) 
{ 
    string toBeFiltered = string.Empty; 

    switch(filterTarget) 
    { 
     case FilterTarget.Body : 
     { toBeFiltered = message.Body; } break; 
     case FilterTarget.AnyOtherProp : 
     { toBeFiltered = message.AnyOtherProp; } break; 
     default: 
     { 
      throw new ArgumentException(
       string.Format("Unsupported property {0}", filterTarget.ToString() 
      ); 
     } 
    } 

    switch (this.operatorEnum) 
    { 
     case FilterParameterOperatorEnum.EqualTo: 
      return message => !string.IsNullOrEmpty(toBeFiltered) && 
           toBeFiltered.Equals(this.value, StringComparison.InvariantCultureIgnoreCase); 

     /* CUT: other cases are similar */ 
    } 
} 

È possibile rendere il metodo FilterData ancora più voglia farla accettare un params FilterTarget[] guadagnando così funzionalità multi-filtraggio (al largo della parte superiore della mia testa, codice non incluso).

Usage:

var aFilterDataResult = FilterData(FilterTarget.Body);  
var anotherFilterDataResult = FilterData(FilterTarget.AnyOtherProp); 
... 
Problemi correlati