Ajith Nair
Ajith Nair

Reputation: 25

Can I dynamically add parameters to LINQ Query for IEnumerable.Any method?

I have created a method which accepts a dynamic list, an object and two parameter names. I want to return a boolean value using Enumerable.Any method with the matching conditions based on the parameter names passed to the mehtod.

public static bool CheckDuplicate(List<T> list, Object obj, string param1, string param2)
{
    return list.Any(item => item.pararm1 = obj.param1 && item.param2 = obj.param2);
}

I want to find the item which matches the value with the obj object based on the conditions provided dynamically.

Upvotes: 2

Views: 1304

Answers (2)

Leighton Ritchie
Leighton Ritchie

Reputation: 501

Seems like what you want is to compare member variables accessed by the name of the member variable. This is known as reflection. Here is my solution:

First add an extension method to help us get member variables by name (from this SO answer):

static class Extension
{
    public static object GetPropValue(this object src, string propName)
    {
        return src.GetType().GetProperty(propName).GetValue(src, null);
    }
}

Then, your function would be:

public static bool CheckDuplicate<T>(IEnumerable<T> list, object obj, string param1, string param2)
    {
        return list.Any(item =>
        item.GetPropValue(param1).Equals(obj.GetPropValue(param1)) &&
        item.GetPropValue(param2).Equals(obj.GetPropValue(param2))
        );
    }

I tested the function with this. It prints True:

static void Main(string[] args)
    {
        var theList = Enumerable.Range(0, 10).Select(i => new Tuple<int, int>(i, i + 1));
        Console.WriteLine(CheckDuplicate(theList, new { Item1 = 5, Item2 = 6 }, "Item1", "Item2"));
        Console.ReadKey();
    }

For use in production, however, you might want to ensure that the param1 and param2 actually exist, and also please lookup and consider the differences between .Equals() and ==. It might be useful to note that the returned values from GetPropValue() are boxed.

Upvotes: 1

Harald Coppoolse
Harald Coppoolse

Reputation: 30454

Consider creating a LINQ-like extension method WhereAll, which does a Where of all predicates that were given as parameter:

static IEnumerable<TSource> WhereAll<TSource>(this IEnumerable<TSource> source
   IEnumerable<Func<TSource, bool>> predicates)
{
    // TODO: exception if source / predicates null

    // return all source elements that have a true for all predicates:
    foreach (var sourceElement in source)
    {
        // check if this sourceElement returns a true for all Predicates:
        if (predicates.All(predicate => predicate(sourceElement))
        {
             // yes, every predicate returns a true
             yield return sourceElement;
        }
        // else: no there are some predicates that return false for this sourceElement
        // skip this element
 }

usage:

List<Person> persons = ...
// Get all Parisians with a Name that were born before the year 2000:
var result = persons.WhereAll(new Func<Person, bool>[]
    {
         person => person.Name != null,
         person => person.BirthDay.Year < 2000,
         person => person.Address.City == "Paris",
    });

Upvotes: 1

Related Questions