I have a list that i would like to filter based on a List of KeyValuePairs. All the keys in the KeyValuePair exist in the object.
So let's say i have a list of objects from this class:
public class filters
{
public string Name { get; set; }
public string Age { get; set; }
public string Country { get; set; }
}
And I have a KeyValuePair with:
Key: "Name", Value: "test"
Key: "Country", Value: "SE"
Is it possible to generate some kind of LINQ predicate from the KeyValuePair that is usable as list.Where(predicate)
, and the predicate would be the same as if I would have written list.Where(c => c.Name == "test" && c.Country == "SE")
?
Or how should I approach this?
You want a
Predicate<filters>
generated from KeyValuePair, which isIEnumerable<KeyValuePair<string, string>>
. So it'sUse reflection to enumerate
All
properties listed in KeyValuePair.Key and check if each property value match KeyValuePair.Value. Full code is likeThis should do the trick:
Result:
You could use an approach like this:
You could also extend the
ToPredicate
method to combine theKeyValuePairs
with something else thanand
.Something like this? Getting the Propertyname through reflection and do an equality check.
As a one-liner:
This enables you to have an unlimited number of filters.
For each
item
in yourlist
theAll
predicate will check the validity for each filter.item.GetType()
gets theType
(ie information about your class) for youritem
.GetProperty(f.Key)
gets information for the specific property, named by theKey
of the current filterf
.GetValue(item)
gets the value of the property for the currentitem
. The?
is a new feature of c# 6, ie it's an inline check fornull
, ie if the property is not found, it does not try to executeGetValue
-- which would raise aNullReferenceException
-- but returnsnull
. You then have to cast the property value tostring
and compare it to theValue
of the current filter. You can also use String::Compare (or any other comparison method you prefer).All
only returnstrue
if all filters are met and false otherwise. So the result of this query will contain all elements which meet all the filters in your DictionaryI might have mis understood you here but does this do what you want:
... or you can wrap the predicate in an extension method ...
... having done that you can filter the original list like this ...