2016-02-11 19 views
6

devo interrogare raccolta in questo modo:LINQ espressione come parametro

myList.Where(s => myFilters.Contains(s.CountryCode)) 

s.CountryCode sopra è un esempio. Voglio rendere variabile e chiamare per diverse colonne, in questo modo:

myList.Where(s => myFilters.Contains(s.City)) 
myList.Where(s => myFilters.Contains(s.Region)) 
myList.Where(s => myFilters.Contains(s.Zipcode)) 

quindi vorrei definire la funzione in cui l'espressione di colonna è un parametro. Qual è la firma di tale funzione?

public void MySelect(???) 
{ 
    myList.Where(s => myFilters.Contains(???); 
} 

myList è un ObservableCollection, e myFilters è List<string>

+0

Penso che si dovrebbe definire il tipo della variabile. –

+1

Dipende dal tipo di dati 'myFilters'. Si prega di estendere la tua domanda con queste informazioni. –

+0

@VadimMartynov Non capisco .... perché è necessario conoscere il tipo di dati myfilters – Viru

risposta

10

Mettere questo metodo di estensione in una classe statica:

public static IEnumerable<T> WhereContains<T, TValue> (this IEnumerable<T> obj, IEnumerable<TValue> container, Func<T, TValue> propertyAccess) 
{ 
    return obj.Where(o => container.Contains(propertyAccess(o))); 
} 

Il modo in cui questo ex il metodo di tensione funziona è che accetta una funzione lambda che risolve la proprietà assegnata a un oggetto del tuo tipo. Quindi devi solo passare un semplice lamba come x => x.City ad esso.

Poiché è completamente generico e non specifico per la tua raccolta myFilters, devi anche passarlo alla funzione. Ma questo ti permette di usare questo WhereContains anche per molte altre situazioni.

Utilizzando sembra che questo:

// Test is a class with two string properties `City` and `Region` 
var myList = new List<Test>{ 
    new Test() { City = "asdf", Region = "fdsa" }, 
    new Test() { City = "foo", Region = "bar" }, 
    new Test() { City = "bar", Region = "baz" } 
}; 

var myFilters = new List<string> { "asdf", "bar" }; 

myList.WhereContains(myFilters, x => x.City); // contains asdf/fdsa and bar/baz 
myList.WhereContains(myFilters, x => x.Region); // contains foo/bar 
+1

Questo è molto meglio che usare la riflessione ... +1 – Viru

+0

Ho usato saltare i metodi generici pensando alla sua struttura complessa. buono. – Manoj

1

È possibile utilizzare Riflessione

public void MySelect(string column) 
{ 
    var result = myList.Where(s => myFilters.Contains(s.GetType().GetProperty(column))); 
} 
0

Come soluzione alternativa è possibile utilizzare il seguente approccio che consente di specificare campo filtro o funzione di filtro:

var adresses = new List<Address>{ 
    new Address() { City = "ABC", Country = "USA" }, 
    new Address() { City = "BC", Country = "USA" }, 
    new Address() { City = "C", Country = "UK" } 
}; 
var filterValues = new List<string> { "B", "UK", "U" }; 
// 
var FilterContains = [email protected]((values, value) => values.Contains(value)); 
var FilterStartsWith = [email protected]((values, value) => values.Any(v => value.StartsWith(v))); 
// 
var AdressesByCity = [email protected](a => a.City); 
var adressesByCitiesContains = AdressesByCity(filterValues, FilterContains); // B->{ABC;USA},{BC;USA} 
var adressesByCitiesStartsWith = AdressesByCity(filterValues, FilterStartsWith);// B->{BC;USA} 
// 
var AdressesByCountry = [email protected](a => a.Country); 
var adressesByCountriesContains = AdressesByCountry(filterValues, FilterContains);//U,UK-> {C;UK} 
var adressesByCountriesStartsWith = AdressesByCountry(filterValues, FilterStartsWith); //U,UK->{ABC;USA},{BC;USA}{C;UK} 

Qui i metodi di estensione @Specify sono implementati come segue:

public static class @SpecifyExtension { 
    public static Func<IEnumerable<V>, Func<IEnumerable<V>, V, bool>, IEnumerable<U>> @Specify<U, V>(this IEnumerable<U> source, Func<U, V> selector) { 
     return (values, predicate) => source.Where(x => predicate(values, selector(x))); 
    } 
    public static Func<IEnumerable<TValue>, TValue, bool> @Specify<TValue>(this IEnumerable<TValue> source, Func<IEnumerable<TValue>, TValue, bool> func) { 
     return func; // for Type-inference only 
    } 
} 
Problemi correlati