2

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.

Johnny
  • 8,939
  • 2
  • 28
  • 33
Ajith Nair
  • 25
  • 1
  • 5
  • 3
    Instead of passing an `Object` and `string`s you can pass a `Func`. But at that point you're literally just defining the `Any()` method and this method becomes pointless. Why not just call `.Any()` in the first place, instead of creating this pass-through method? – David Apr 25 '19 at 10:48

2 Answers2

1

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",
    });
Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
1

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.

Leighton Ritchie
  • 501
  • 4
  • 15