2

I´m trying to do something like this:

     public class Person{string name;string surname;}
     //...
     List<Person> listExample;
     //We add Person object in listExample
     string variable="name";
     listexample.Where(x=>x.(variable)=="John");

Is it posible to do something similar ?

  • 1
    Possible duplicate of [How to create predicate dynamically](http://stackoverflow.com/questions/6383825/how-to-create-predicate-dynamically); also [Dynamically-create-an-expression](http://stackoverflow.com/questions/5094489/how-do-i-dynamically-create-an-expressionfuncmyclass-bool-predicate-from-ex); also [dynamically-create-predicate)](http://stackoverflow.com/questions/845059/how-do-i-dynamically-create-an-expressionfuncmyclass-bool-predicate) – ASh May 05 '16 at 17:34

3 Answers3

0

If you need to access non-public fields then you can use reflection:

class Person
{
    public Person(string name)
    {
        this.name = name;
    }

    string name;
}

List<Person> people = new List<Person>()
{
    new Person("Jane"),
    new Person("John")
};

string variableName = "name";
string criteria = "John";

var selectedPeople =
    people
        .Where(person =>
            typeof(Person)
                .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                .Where(fieldInfo => String.Equals(fieldInfo.Name, variableName))
                .Select(fieldInfo => fieldInfo.GetValue(person) as string)
                .SingleOrDefault() == criteria
        )
        .ToList();

// At this point 'selectedPeople' will contain one 'Person' named "John"

If you need to access properties then you can use GetProperties(BindingFlags bindingAttr) method instead of GetFields(...) method.

class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public string Name { get; set; }
}

// in a method
var selectedPeople =
    people
        .Where(person =>
            typeof(Person)
                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(propertyInfo => String.Equals(propertyInfo.Name, variableName))
                .Select(propertyInfo => propertyInfo.GetValue(person) as string)
                .SingleOrDefault() == criteria
        )
        .ToList();

You should take a look at BindingFlags enum so that you can select the appropriate enum values.

  • BindingFlags.Static for static members
  • BindingFlags.Instance for instance members
  • BindingFlags.Public for public members
  • BindingFlags.NonPublic for private / protected members
  • etc.
Gabor
  • 3,021
  • 1
  • 11
  • 20
0

The easiest way, considering the class has only two possible fields to filter on, would be to use simple if-else block :

string targetProperty = "name";
string targetValue = "John";
IEnumerable<Person> query = listExample;

if(targetProperty == "name") query = query.Where(x => x.name == targetValue)
else if(targetProperty == "surname") query = query.Where(x => x.surname == targetValue)

var result = query.ToList();

If the actual class has a lot of possible properties/fields to filter on, and you want to avoid too many if-branches, it's time to use Expression as mentioned in the comment below the question :

string targetProperty = "name";
string targetValue = "John";

var param = Expression.Parameter(typeof(Person), "x");
var body = Expression.Equal(
                Expression.PropertyOrField(param, targetProperty),
                Expression.Constant(targetValue));
var predicate = Expression.Lambda<Func<Person, bool>>(body, param);

var result = listExample.Where(predicate.Compile()).ToList();

The above codes should build predicate expression equivalent to x => x.name == "John" (since targetProperty = "name" and targetValue = "John")

har07
  • 88,338
  • 12
  • 84
  • 137
0

There's a nuget package for this that lets you write;

using System.Linq.Dynamic; //Import the Dynamic LINQ library

//The standard way, which requires compile-time knowledge
//of the data model
var result = myQuery
    .Where(x => x.Field1 == "SomeValue")
    .Select(x => new { x.Field1, x.Field2 });

//The Dynamic LINQ way, which lets you do the same thing
//without knowing the data model before hand
var result = myQuery
    .Where("Field1=\"SomeValue\"")
    .Select("new (Field1, Field2)");
Steve Cooper
  • 20,542
  • 15
  • 71
  • 88